[Scummvm-cvs-logs] scummvm master -> 15ea9b15cbb1210b14490819c5bc04f72ed7e6c8
athrxx
athrxx at scummvm.org
Mon May 16 23:21:55 CEST 2011
This automated email contains information about 30 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
ee89e9a086 VKEYBD: Update vkeybd_default.zip
b4d59f9ce5 FM-TOWNS AUDIO: some more midi driver code for FM-TOWNS versions of monkey2 and indy4
f98be17d74 FM-TOWNS AUDIO: fix compilation
afacbd459f FM-TOWNS AUDIO: change internal interface layout
61c5813ccf MONKEY2/INDY4 FM-TOWNS: adapt code to latest audio driver changes
ad991a7831 FM TOWNS AUDIO: implement some midi driver functions
0dce8bab37 FM-TOWNS AUDIO: implement some more midi driver code
df244dd3c1 FM TOWNS AUDIO: some more midi driver code
70b2466cd7 FM-TOWNS AUDIO: implement some midi commands
39e2aa17ed FM-TOWNS AUDIO: more midi driver code (effect processing)
0e819b8dfa FM-TOWNS AUDIO: some renaming in the euphony driver code
ed13e551d1 FM-TOWNS AUDIO: more midi driver code
17861037ba MONKEY2 / INDY4 FM-TOWNS: set proper GUIO flags
78130f940f FM-TOWNS AUDIO: start fixing midi driver tempo
214a70002f FM-TOWNS AUDIO: fixed mod wheel setting
41edb7c6b5 FM-TOWNS AUDIO: some more midi driver code
232cb2410c FM-TOWNS AUDIO: improve thread safety
66d19fde68 FM-TOWNS AUDIO: some midi code fixes and some renaming
e1ac2882bc SCUMM: add missing imuse feature
bbbde5aa67 FM-TOWNS AUDIO: fix some midi driver bugs
73d5b9f595 FM-TOWNS AUDIO: fix note off event in midi driver
13497a9b0f SCUMM: fix recent commit (proper initialize new detune parameter)
f9eb329c79 FM-TOWNS AUDIO: fix some bugs and rename some stuff in the midi driver code
a9f7888ad9 FM TOWNS AUDIO: some fixes and renaming
747b86433c SCUMM: partly revert / fix recent detune commit
52e4f162dd FMTOWNS AUDIO: fix several CppCheck warnings
cd359cab1b GOB: Add a non-interactive Adibou2 demo
7fd78c5998 FM-TOWNS AUDIO: fix GCC warnings
7a489ef005 Merge branch 'master' of git://github.com/scummvm/scummvm
15ea9b15cb SCUMM FM-TOWNS: iMUSE MIDI driver for INDY4/MONKEY2
Commit: ee89e9a0866fd0c292de8f29d236d1e7d4be70b3
https://github.com/scummvm/scummvm/commit/ee89e9a0866fd0c292de8f29d236d1e7d4be70b3
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:14-07:00
Commit Message:
VKEYBD: Update vkeybd_default.zip
Specifically, in vkeybd_default.xml, 'centre' changed to 'center'.
SCUMM: formatting
README: Add partial translations of README file
This add an english template for translation of README file and
French and German translations (using UTF8 encoding).
ENGINES: Unify engine names
This unifies the engine names in MetaEngine::getName() and the
credits. In particular drop "Engine" or "engine" from the names when
it was present and use expanded names in credits when the
MetaEngine uses it (e.g. "Beneath a Steel Sky" instead of "BASS").
GUI: Apply graphics mode change when closing global options dialog
IPHONE: Fixed mouse position when the overlay is visible
TSAGE: Fix bad palette in the Fleeing planet cutscene
It was using out-of-bounds data to manipulate the palette, and a
missing break caused it to change palette again immediately. Still,
even after this change I had the impression that the temporary
palette was visible for a bit longer in DOSBox. Could be my
imagination, though.
TSAGE: Fix for crash when hiding cursor in Ringworld demo
TSAGE: Implemented the Exit dialog in the Ringworld demo
TSAGE: Bugfixes for dialogs correctly handling ESCAPE and ENTER
TSAGE: Changed demo quit dialog to correctly handle ESCAPE and ENTER keys
TSAGE: Added support for handling keypresses in the Game classes. Separated logic for full game versus demo into the respective Game classes.
COMMON: Set _capacity to just _size in Common::Array::operator=
COMMON: Change Array::insert_aux to immediately assign newly allocated memory to _storage
COMMON: Unify Array memory allocation
We also change how alloc failures are handled: Instead of using
assert(), which is usually disabled in release builds on various
platforms, we now *always* catch this situation and invoke error() if
necessary.
COMMON: Don't allocate zero-sized storage in array
AUDIO: Clarify required parameters for mixCallback.
Also, add an assert() to make invalid lengths obvious.
TEST: Explicitly disable exceptions and std lib usage
COMMON: Fix inserting an array into itself under certain conditions
SCUMM: fix regression
Merge branch 'master' of https://github.com/scummvm/scummvm
VKEYBD: Update vkeybd_default.zip
Specifically, in vkeybd_default.xml, 'centre' changed to 'center'.
SCUMM: formatting
README: Add partial translations of README file
This add an english template for translation of README file and
French and German translations (using UTF8 encoding).
ENGINES: Unify engine names
This unifies the engine names in MetaEngine::getName() and the
credits. In particular drop "Engine" or "engine" from the names when
it was present and use expanded names in credits when the
MetaEngine uses it (e.g. "Beneath a Steel Sky" instead of "BASS").
GUI: Apply graphics mode change when closing global options dialog
IPHONE: Fixed mouse position when the overlay is visible
TSAGE: Fix bad palette in the Fleeing planet cutscene
It was using out-of-bounds data to manipulate the palette, and a
missing break caused it to change palette again immediately. Still,
even after this change I had the impression that the temporary
palette was visible for a bit longer in DOSBox. Could be my
imagination, though.
Merge branch 'master' of git://github.com/scummvm/scummvm
TSAGE: Fix for crash when hiding cursor in Ringworld demo
TSAGE: Implemented the Exit dialog in the Ringworld demo
TSAGE: Bugfixes for dialogs correctly handling ESCAPE and ENTER
TSAGE: Changed demo quit dialog to correctly handle ESCAPE and ENTER keys
TSAGE: Added support for handling keypresses in the Game classes. Separated logic for full game versus demo into the respective Game classes.
COMMON: Set _capacity to just _size in Common::Array::operator=
COMMON: Change Array::insert_aux to immediately assign newly allocated memory to _storage
COMMON: Unify Array memory allocation
We also change how alloc failures are handled: Instead of using
assert(), which is usually disabled in release builds on various
platforms, we now *always* catch this situation and invoke error() if
necessary.
COMMON: Don't allocate zero-sized storage in array
AUDIO: Clarify required parameters for mixCallback.
Also, add an assert() to make invalid lengths obvious.
TEST: Explicitly disable exceptions and std lib usage
COMMON: Fix inserting an array into itself under certain conditions
SCUMM: fix regression
Merge branch 'master' of https://github.com/scummvm/scummvm
Merge branch 'master' of git://github.com/scummvm/scummvm
Changed paths:
A doc/translations/README-de.txt
A doc/translations/README-fr.txt
A doc/translations/README-translation_template.txt
AUTHORS
audio/mixer.cpp
audio/mixer_intern.h
backends/platform/iphone/iphone_video.m
backends/vkeybd/packs/vkeybd_default.zip
common/array.h
devtools/credits.pl
engines/agi/detection.cpp
engines/cine/detection.cpp
engines/cruise/detection.cpp
engines/draci/detection.cpp
engines/drascula/detection.cpp
engines/gob/detection.cpp
engines/groovie/detection.cpp
engines/hugo/detection.cpp
engines/kyra/detection.cpp
engines/lastexpress/detection.cpp
engines/lure/detection.cpp
engines/m4/detection.cpp
engines/made/detection.cpp
engines/mohawk/detection.cpp
engines/parallaction/detection.cpp
engines/saga/detection.cpp
engines/sci/detection.cpp
engines/scumm/detection.cpp
engines/scumm/imuse/imuse.cpp
engines/sword25/detection.cpp
engines/teenagent/detection.cpp
engines/tinsel/detection.cpp
engines/toon/detection.cpp
engines/touche/detection.cpp
engines/tsage/core.cpp
engines/tsage/detection.cpp
engines/tsage/events.cpp
engines/tsage/graphics.cpp
engines/tsage/ringworld_demo.cpp
engines/tsage/ringworld_demo.h
engines/tsage/ringworld_logic.cpp
engines/tsage/ringworld_logic.h
engines/tsage/ringworld_scenes2.cpp
engines/tsage/scenes.h
engines/tsage/staticres.cpp
engines/tsage/staticres.h
engines/tucker/detection.cpp
gui/credits.h
gui/options.cpp
test/common/array.h
test/module.mk
diff --git a/AUTHORS b/AUTHORS
index ca6342d..d8d26ce 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -49,7 +49,7 @@ ScummVM Team
Oliver Kiehl - (retired)
Ludvig Strigeus - (retired)
- BASS:
+ Beneath a Steel Sky:
Robert Goeffringmann - (retired)
Oliver Kiehl - (retired)
Joost Peters
@@ -82,7 +82,7 @@ ScummVM Team
Paul Gilbert
Vincent Hamm - (retired)
- Draci:
+ Draci Historie:
Denis Kasak
Robert Spalek
@@ -90,7 +90,7 @@ ScummVM Team
Filippos Karapetis
Pawel Kolodziejski
- FOTAQ:
+ Flight of the Amazon Queen:
David Eriksson - (retired)
Gregory Montoir
Joost Peters
@@ -111,7 +111,7 @@ ScummVM Team
Oystein Eftevaag
Eugene Sandulenko
- Kyra:
+ Legend of Kyrandia:
Torbjorn Andersson - VQA Player
Oystein Eftevaag
Florian Kagerer
@@ -123,7 +123,7 @@ ScummVM Team
Jordi Vilalta Prat
Julien Templier
- Lure:
+ Lure of the Temptress:
Paul Gilbert
M4:
@@ -164,7 +164,7 @@ ScummVM Team
Jordi Vilalta Prat
Lars Skovlund
- TeenAgent:
+ Teen Agent:
Robert Megone - Help with callback rewriting
Vladimir Menshakov
diff --git a/audio/mixer.cpp b/audio/mixer.cpp
index 3482bd3..fb4fffb 100644
--- a/audio/mixer.cpp
+++ b/audio/mixer.cpp
@@ -257,6 +257,8 @@ int MixerImpl::mixCallback(byte *samples, uint len) {
Common::StackLock lock(_mutex);
int16 *buf = (int16 *)samples;
+ // we store stereo, 16-bit samples
+ assert(len % 4 == 0);
len >>= 2;
// Since the mixer callback has been called, the mixer must be ready...
diff --git a/audio/mixer_intern.h b/audio/mixer_intern.h
index 05e519c..a04eb55 100644
--- a/audio/mixer_intern.h
+++ b/audio/mixer_intern.h
@@ -126,6 +126,8 @@ public:
* the backend (e.g. from an audio mixing thread). All the actual mixing
* work is done from here.
*
+ * @param samples Sample buffer, in which stereo 16-bit samples will be stored.
+ * @param len Length of the provided buffer to fill (in bytes, should be divisible by 4).
* @return number of sample pairs processed (which can still be silence!)
*/
int mixCallback(byte *samples, uint len);
diff --git a/backends/platform/iphone/iphone_video.m b/backends/platform/iphone/iphone_video.m
index 09832c7..006603d 100644
--- a/backends/platform/iphone/iphone_video.m
+++ b/backends/platform/iphone/iphone_video.m
@@ -175,13 +175,18 @@ const char* iPhone_getDocumentsDir() {
}
bool getLocalMouseCoords(CGPoint *point) {
- if (point->x < _screenRect.origin.x || point->x >= _screenRect.origin.x + _screenRect.size.width ||
- point->y < _screenRect.origin.y || point->y >= _screenRect.origin.y + _screenRect.size.height) {
- return false;
- }
+ if (_overlayIsEnabled) {
+ point->x = point->x / _overlayHeight;
+ point->y = point->y / _overlayWidth;
+ } else {
+ if (point->x < _screenRect.origin.x || point->x >= _screenRect.origin.x + _screenRect.size.width ||
+ point->y < _screenRect.origin.y || point->y >= _screenRect.origin.y + _screenRect.size.height) {
+ return false;
+ }
- point->x = (point->x - _screenRect.origin.x) / _screenRect.size.width;
- point->y = (point->y - _screenRect.origin.y) / _screenRect.size.height;
+ point->x = (point->x - _screenRect.origin.x) / _screenRect.size.width;
+ point->y = (point->y - _screenRect.origin.y) / _screenRect.size.height;
+ }
return true;
}
diff --git a/backends/vkeybd/packs/vkeybd_default.zip b/backends/vkeybd/packs/vkeybd_default.zip
index 94c4649..960e943 100644
Binary files a/backends/vkeybd/packs/vkeybd_default.zip and b/backends/vkeybd/packs/vkeybd_default.zip differ
diff --git a/common/array.h b/common/array.h
index 9b94709..7ab4a1b 100644
--- a/common/array.h
+++ b/common/array.h
@@ -24,6 +24,7 @@
#include "common/scummsys.h"
#include "common/algorithm.h"
+#include "common/textconsole.h" // For error()
namespace Common {
@@ -72,8 +73,7 @@ public:
Array(const Array<T> &array) : _capacity(array._size), _size(array._size), _storage(0) {
if (array._storage) {
- _storage = new T[_capacity];
- assert(_storage);
+ allocCapacity(_size);
copy(array._storage, array._storage + _size, _storage);
}
}
@@ -83,9 +83,8 @@ public:
*/
template<class T2>
Array(const T2 *data, int n) {
- _capacity = _size = n;
- _storage = new T[_capacity];
- assert(_storage);
+ _size = n;
+ allocCapacity(n);
copy(data, data + _size, _storage);
}
@@ -179,9 +178,7 @@ public:
delete[] _storage;
_size = array._size;
- _capacity = _size + 32;
- _storage = new T[_capacity];
- assert(_storage);
+ allocCapacity(_size);
copy(array._storage, array._storage + _size, _storage);
return *this;
@@ -238,15 +235,13 @@ public:
if (newCapacity <= _capacity)
return;
- T *old_storage = _storage;
- _capacity = newCapacity;
- _storage = new T[newCapacity];
- assert(_storage);
+ T *oldStorage = _storage;
+ allocCapacity(newCapacity);
- if (old_storage) {
+ if (oldStorage) {
// Copy old data
- copy(old_storage, old_storage + _size, _storage);
- delete[] old_storage;
+ copy(oldStorage, oldStorage + _size, _storage);
+ delete[] oldStorage;
}
}
@@ -267,6 +262,17 @@ protected:
return capa;
}
+ void allocCapacity(uint capacity) {
+ _capacity = capacity;
+ if (capacity) {
+ _storage = new T[capacity];
+ if (!_storage)
+ ::error("Common::Array: failure to allocate %d bytes", capacity);
+ } else {
+ _storage = 0;
+ }
+ }
+
/**
* Insert a range of elements coming from this or another array.
* Unlike std::vector::insert, this method does not accept
@@ -286,29 +292,28 @@ protected:
const uint n = last - first;
if (n) {
const uint idx = pos - _storage;
- T *newStorage = _storage;
- if (_size + n > _capacity) {
+ T *oldStorage = _storage;
+ if (_size + n > _capacity || (_storage <= first && first <= _storage + _size) ) {
// If there is not enough space, allocate more and
// copy old elements over.
- uint newCapacity = roundUpCapacity(_size + n);
- newStorage = new T[newCapacity];
- assert(newStorage);
- copy(_storage, _storage + idx, newStorage);
- pos = newStorage + idx;
+ // Likewise, if this is a self-insert, we allocate new
+ // storage to avoid conflicts. This is not the most efficient
+ // way to ensure that, but probably the simplest on.
+ allocCapacity(roundUpCapacity(_size + n));
+ copy(oldStorage, oldStorage + idx, _storage);
+ pos = _storage + idx;
}
// Make room for the new elements by shifting back
// existing ones.
- copy_backward(_storage + idx, _storage + _size, newStorage + _size + n);
+ copy_backward(oldStorage + idx, oldStorage + _size, _storage + _size + n);
// Insert the new elements.
copy(first, last, pos);
// Finally, update the internal state
- if (newStorage != _storage) {
- delete[] _storage;
- _capacity = roundUpCapacity(_size + n);
- _storage = newStorage;
+ if (_storage != oldStorage) {
+ delete[] oldStorage;
}
_size += n;
}
diff --git a/devtools/credits.pl b/devtools/credits.pl
index 46c7540..8d02891 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -500,7 +500,7 @@ begin_credits("Credits");
add_person("Ludvig Strigeus", "ludde", "(retired)");
end_section();
- begin_section("BASS"); # Beneath a Steel Sky
+ begin_section("Beneath a Steel Sky");
add_person("Robert Göffringmann", "lavosspawn", "(retired)");
add_person("Oliver Kiehl", "olki", "(retired)");
add_person("Joost Peters", "joostp", "");
@@ -539,7 +539,7 @@ begin_credits("Credits");
add_person("Vincent Hamm", "yaz0r", "(retired)");
end_section();
- begin_section("Draci");
+ begin_section("Draci Historie");
add_person("Denis Kasak", "dkasak13", "");
add_person("Robert Špalek", "spalek", "");
end_section();
@@ -549,7 +549,7 @@ begin_credits("Credits");
add_person("Paweł Kołodziejski", "aquadran", "");
end_section();
- begin_section("FOTAQ"); # Flight of the Amazon Queen
+ begin_section("Flight of the Amazon Queen");
add_person("David Eriksson", "twogood", "(retired)");
add_person("Gregory Montoir", "cyx", "");
add_person("Joost Peters", "joostp", "");
@@ -574,7 +574,7 @@ begin_credits("Credits");
add_person("Eugene Sandulenko", "sev", "");
end_section();
- begin_section("Kyra");
+ begin_section("Legend of Kyrandia");
add_person("Torbjörn Andersson", "eriktorbjorn", "VQA Player");
add_person("Oystein Eftevaag", "vinterstum", "");
add_person("Florian Kagerer", "athrxx", "");
@@ -588,7 +588,7 @@ begin_credits("Credits");
add_person("Julien Templier", "littleboy", "");
end_section();
- begin_section("Lure");
+ begin_section("Lure of the Temptress");
add_person("Paul Gilbert", "dreammaster", "");
end_section();
@@ -636,7 +636,7 @@ begin_credits("Credits");
add_person("Lars Skovlund", "lskovlun", "");
end_section();
- begin_section("TeenAgent");
+ begin_section("Teen Agent");
add_person("Robert Megone", "sanguine", "Help with callback rewriting");
add_person("Vladimir Menshakov", "whoozle", "");
end_section();
diff --git a/doc/translations/README-de.txt b/doc/translations/README-de.txt
new file mode 100755
index 0000000..a1d7d6e
--- /dev/null
+++ b/doc/translations/README-de.txt
@@ -0,0 +1,178 @@
+Dieses Dokument ist eine auszugsweise Übersetzung der englischen
+REAMDE-Datei. Das Original-Dokument enthält viel mehr Informationen.
+Sollten Sie hier also nicht das finden, was Sie benötigen und ein wenig
+Englisch können, sollten Sie sich die englische README-Datei ansehen.
+
+Für weitere Informationen, Kompatiblitätslisten, Einzelheiten zu Spenden,
+die neusten veröffentlichten Versionen, Fortschrittberichte und mehr
+besuchen Sie bitte die ScummVM-Website unter der Adresse:
+http://www.scummvm.org/
+
+Inhaltsverzeichnis:
+------------------
+1.0) Einführung
+ * 1.1 Über ScummVM
+ * 1.2 Schnellstart
+2.0) Kontakt
+ * 2.1 Fehler berichten
+
+1.0) Einführung:
+---- -------------
+
+1.1) Über ScummVM:
+---- --------------
+ScummVM ist ein Programm, welches es Ihnen ermöglicht, bestimmte klassische
+Grafik-Adventure (unter anderem aus dem Point-and-Click-Bereich) zu spielen,
+vorausgesetzt, Sie sind im Besitz der Dateien des Spiels. Das Schlaue daran
+ist: ScummVM ersetzt lediglich die Funktion der ausführbaren Dateien,
+die mit den Spielen kamen, was ermöglicht, diese Spiele auf Systemen zu spielen,
+für welche sie nie erstellt wurden!
+
+Ursprünglich wurde dieses Programm dafür entwickelt, um SCUMM-Spiele von
+LucasArts auszuführen, wie beispielsweise Maniac Mansion, Monkey Island,
+Day of the Tentacle oder Sam and Max. SCUMM steht als Abkürzung für
+„Script Creation Utility for Maniac Mansion“ (deutsch etwa:
+Skripterstellungsdienstprogramm für Maniac Mansion), was das erste
+Spiel von LucasArts war, für welches LucasArts dieses System entworfen hatte.
+Und viel später verlieh es seinen Namen an ScummVM (wobei „VM“ für
+„Virtuelle Maschine“ steht).
+
+Mit der Zeit wurde Unterstützung für viele Nicht-SCUMM-Spiele hinzugefügt.
+Einige Adventures, die ScummVM unterstützt, sind unter anderem Simon the
+Sorcerer 1 und 2 von Adventure Soft, Beneath A Steel Sky und
+Baphomets Fluch 1 und 2 von Revolution, Flight of the Amazon Queen,
+Erben der Erde (Wyrmkeep), Gobliiins von Coktel Vision sowie
+The Legend of Kyrandia von Westwood Studios.
+Sie können eine genaue Liste mit Einzelheiten einsehen, welche Auskunft
+darüber gibt, welche Spiele unterstützt werden und wie gut. Gehen Sie
+hierfür auf die Kompatiblitätsseite. ScummVM wird kontinuierlich
+verbessert, also schauen Sie oft vorbei.
+
+Unter den Systemen, mit denen Sie diese Spiele spielen können, befinden
+sich Windows, Linux, Mac OS X, Dreamcast, PocketPC, PalmOS, iPhone,
+AmigaOS, BeOS, OS/2, PSP, PS2, SymbianOS/EPOC und viele mehr.
+
+Zurzeit befindet sich ScummVM immer noch stark in der Entwicklung.
+Seien Sie sich bewusst, dass wir zwar versuchen, dass viele Spiele
+mit wenigen erheblichen Fehlern durchgespielt werden können, aber es
+dennoch zu Abstürzen kommen kann und wir keine Gewähr übernehmen.
+Davon abgesehen: Einige Spiele werden seit längerer Zeit unterstützt
+und sollten in jeder stabilen veröffentlichten Version gut laufen.
+Sie können sich einen Eindruck davon verschaffen, wie gut jedes Spiel
+unter ScummVM läuft, indem Sie auf die Kompatiblitätsseite schauen.
+
+Wenn Sie sich ein wenig umsehen, können Sie herausfinden, dass
+ScummVM sogar kommerziell genutzt wird, um einige der unterstützen Spiele
+auf modernen Plattformen wiederzuveröffentlichen. Dies zeigt, dass
+verschiedene Firmen mit der Qualität der Software zufrieden sind und wie gut
+einige der Spiele mit ihrer Hilfe laufen.
+
+Wenn Ihnen ScummVM gefällt, können Sie uns gerne etwas Geld spenden,
+um uns finanziell zu unterstützen. Dies hilft uns dabei, notwendige
+Dienstprogramme zu kaufen, um ScummVM einfacher und schneller zu entwickeln.
+Wenn Sie nicht spenden können, dürfen Sie auch gerne einen Patch beisteuern.
+
+1.2) Schnellstart:
+---- ------------
+WICHTIG: In der unteren kurzen Anleitung wird davon ausgegangen, dass Sie
+ScummVM auf Deutsch benutzen. Standardmäßig wird ScummVM die Sprache
+Ihres Betriebssystems verwenden. Falls ScummVM auf Englisch statt auf
+Deutsch erscheint, sollten Sie folgende Schritte ausführen, wenn Sie bei
+Schritt 3 angelangt sind und ScummVM gestartet haben:
+-Klicken Sie auf "Options".
+-Klicken Sie auf den rechten Pfeil in der Reiterleiste und wählen den
+ Reiter "Misc" aus.
+-Wählen Sie im Feld "GUI Language" "Deutsch" aus und klicken auf "OK".
+-Bestätigen Sie die erscheinende Nachricht, klicken auf "Quit", um
+ ScummVM zu beenden und starten dann das Programm erneut.
+
+Wenn Sie ScummVM lieber in Englisch verwenden möchten, benutzen Sie bitte
+die Anleitung in der englischen README-Datei.
+
+
+Für die ungelduldigen unter den Benutzern ist hier in fünf einfachen
+Schritten kurz beschrieben, wie man ScummVM lauffähig macht und das
+Programm verwendet.
+
+1. Laden Sie ScummVM unter der Adresse
+<http://www.scummvm.org/downloads.php> herunter und installieren Sie es.
+
+2. Erstellen Sie ein Verzeichnis auf Ihrer Festplatte und kopieren Sie
+die Dateien des Spiels vom Original-Datenträger in dieses Verzeichnis.
+Wiederholen Sie diesen Vorgang für jedes Spiel, das Sie spielen möchten.
+
+3. Starten Sie ScummVM, wählen Sie "Spiel hinzufügen" aus, wählen Sie das
+Verzeichnis mit den Dateien des Spiels aus (versuchen Sie nicht, die
+Dateien des Spiels selbst auszuwählen!) und klicken Sie auf "Auswählen".
+
+4. Ein Dialog sollte erscheinen, der Ihnen ermöglicht, verschiedene
+Einstellungen vorzunehmn, sollten Sie dies wünschen (es sollte jedoch in
+Ordnung sein, alles voreingestellt zu belassen). Bestätigen Sie diesen
+Dialog.
+
+5. Wählen Sie das Spiel aus der Liste aus, welches Sie spielen möchten
+und klicken Sie auf "Starten".
+
+In Zukunft sollte es nun möglich sein, direkt zu Schritt 5 überzugehen,
+außer Sie wollen noch mehr Spiele hinzufügen.
+
+Tipp: Wenn Sie mehrere Spiele auf einmal hinzufügen möchten, drücken Sie
+die Umschalt-Taste (Shift), bevor Sie auf "Spiel hinzufügen" klicken.
+Diese Schaltfläche wird somit ihren Text zu "Durchsuchen" umändern und
+wenn Sie dann auf diese klicken, werden Sie auch dazu aufgefordert, ein
+Verzeichnis auszuwählen, nur dieses Mal wird ScummVM alle
+Unterverzeichnisse automatisch nach unterstützen Spielen durchsuchen.
+
+
+2.0) Kontakt:
+---- --------
+Der einfachste Weg, um mit dem ScummVM-Team in Verbindung zu treten, ist,
+Fehlerberichte einzusenden (siehe Abschnitt 2.1) oder durch Verwendung
+des Forums unter der Adresse http://forums.scummvm.org .
+Sie können ebenso der Mailing-Liste scummvm-devel betreiten und an diese
+E-Mails versenden oder mit uns im IRC chatten (#scummvm unter
+irc.freenode.net). Bitte fordern Sie uns nicht dazu auf, ein nicht
+unterstütztes Spiel zu unterstützen. Lesen Sie zuerst die Seite FAQ
+(Häufig gestellte Fragen) auf unserer Website.
+Bitte beachten Sie Kenntnis, dass die offizielle Sprache des Forums,
+der Mailing-Liste und des Chats Englisch ist und keine andere Sprache
+dort verwendet werden sollte.
+
+
+2.1) Fehler berichten:
+---- ---------------
+Um einen Fehler zu berichten, erstellen Sie bitte ein SourceForge-Konto
+und folgen Sie dem Link "Bug Tracker" auf der ScummVM-Website. Bitte
+stellen Sie sicher, dass sich der Bug wiedererzeugen lässt und immer noch
+in der neusten Version von SVN oder des Daily builds auftritt. Bitte
+sehen Sie auch auf der Problemliste unten und der Kompatiblitätsliste auf
+der ScummVM-Website für dieses Spiel nach, um sicherzustellen, dass das
+Problem nicht bereits bekannt ist:
+
+ http://www.scummvm.org/compatibility_stable.php
+
+Bitte berichten Sie keine Fehler zu Spielen, die nicht als durchspielbar
+im Bereich "Supported Games" oder der Kompatiblitätsliste aufgelistet
+sind. Wir -wissen-, dass diese Spiele Fehler aufweisen.
+
+Bitte liefern Sie folgende Informationen:
+ - ScummVM-Version (BITTE mit neuster Version von SVN oder
+ des Daily builds testen)
+ - Einzelheiten zum Fehler, einschließlich Anweisungen, um den Fehler
+ hervorzurufen
+ - Sprache des Spiels (Englisch, Deutsch, ...)
+ - Version des Spiels (Version mit Sprachausgabe [Talkie],
+ Disketten-Version, ...)
+ - Plattform und gegebenenfalls Compiler (Win32, Linux, FreeBSD, ...)
+ - Fügen Sie einen Speicherstand hinzu, wenn es möglich ist.
+ - Wenn dieser Fehler erst seit kurzem Auftritt, teilen Sie bitte die
+ letzte Version ohne den Fehler mit und die erste Version mit diesem
+ Fehler. Auf diese Weise können wir diesen schneller beseitigen,
+ indem wir die vorgenommen Veränderungen einsehen.
+
+Zum Schluss möchten wir Sie noch bitten, jeden Punkt einzeln zu
+berichten; bitte senden Sie nicht mehrere Punkte mit dem selben Ticket
+ein, ansonsten wird es schwierig, den Status jedes einzelnen Fehlers
+zu verfolgen. Denken Sie bitte auch daran, dass alle Fehlerberichte in
+Englisch verfasst sein müssen.
+
diff --git a/doc/translations/README-fr.txt b/doc/translations/README-fr.txt
new file mode 100755
index 0000000..186f0cd
--- /dev/null
+++ b/doc/translations/README-fr.txt
@@ -0,0 +1,172 @@
+Ce document est une traduction partielle du fichier README anglais. Le
+document original contient bien plus d'informations, donc si vous ne
+trouvez pas ce que vous cherchez dans ce document et que vous comprenez
+un peu l'anglais, jetez un coup d'oeil au fichier README anglais.
+
+Pour plus d'informations, liste des jeux compatibles, détails pour
+donner de l'argent, la dernière version disponibles et bien plus encore,
+visitez le site web de ScummVM à l'adresse http://www.scummvm.org/
+
+Table des matières:
+-------------------
+1.0) Introduction
+ * 1.1 À propos de ScummVM
+ * 1.2 Démarrage rapide
+2.0) Contact
+ * 2.1 Signaler des bogues
+
+1.0) Introduction:
+---- -------------
+
+1.1) À propos de ScummVM:
+---- --------------------
+ScummVM est un logiciel qui vous permet de jouer certain jeux
+d'aventures graphiques de type 'point-and-click' (pointer et cliquer), à
+condition que vous possédiez les fichiers de données du jeu. Le plus
+astucieux: ScummVM remplace juste les exécutables fournis avec les jeux,
+vous permettant de jouer sur les systèmes pour lesquels ils n'ont jamais
+été conçus!
+
+A l'origine il a été conçu pour exécuter les jeux basé sur le système
+SCUMM de LucasArts, tels que Maniac Mansion, Monkey Island, Day of the
+Tentacle ou Sam et Max. SCUMM est l'acronyme de 'Script Creation Utility
+for Maniac Mansion', qui a été le premier jeu pour lequel LucasArts a
+conçu ce système. Et beaucoup plus tard, il donna son nom à ScummVM
+('VM' signifiant Virtual Machine).
+
+Au cours du temps de nombreux jeux non-SCUMM ont été ajouté, et ScummVM
+prend désormais en charge de nombreux jeux Sierra AGI et SCI (tels que
+King's Quest 1-6, Space Quest 1-5, ...), Discworld 1 et 2, Simon the
+Sorcerer 1 et 2, Beneath A Steel Sky, Lure of the Temptress, Les
+Chevaliers de Baphomet (Broken Sword I), Les Boucliers de Quetzalcoatl
+(Broken Sword II), L'amazone queen (Flight of the Amazon Queen),
+Gobliiins 1-3, la série des Legend of Kyrandia, un grand nombre de jeux
+pour enfants de Humongous Entertainment (incluant les jeux Marine Malice
+et Pouce-Pouce) et beaucoup plus. Vous pouvez trouver une liste complète
+et détaillée sur les aventures qui sont pris en charge et les problèmes
+connus sur la page de compatibilité. ScummVM évolue en permanence, donc
+vérifier cette liste de compatibilités souvent.
+
+Vous pouvez jouer à ces jeux sur des ordinateurs de bureau classiques
+(sous Windows, Linux, Mac OS X, ...), sur des consoles (Dreamcast,
+Nintendo DS et Wii, PS2, PSP, ...), smartphones (Android, iPhone, Pocket
+PC, Symbian ...) et plus encore.
+
+À ce stade ScummVM est encore en cours de développement. Soyez conscient
+que malgré tous nos efforts pour en faire un logiciel le plus stable
+possible, des plantages peuvent survenir. et nous n'offrons aucune
+garantie. Cela étant dit, certains jeux sont supportés depuis longtemps
+et devrait fonctionner correctement avec une version stable et récente
+de ScummVM. Vous pouvez vous faire une idée du niveau de support d'un
+jeu en regardant la page de compatibilité. En fait, si vous cherchez un
+peu vous pourrez découvrir que ScummVM est même utilisé dans le commerce
+pour la ré-édition sur les plates-formes modernes de quelques-uns des
+jeux supportés. Cela montre que plusieurs entreprises sont satisfaits de
+la qualité du logiciel.
+
+Si vous aimez ScummVM n'hésitez pas à faire un don en utilisant le
+bouton PayPal sur la page d'accueil ScummVM. Cela nous aidera à acheter
+les services nécessaires pour rendre le développement de ScummVM plus
+facile et plus rapide. Si vous ne pouvez pas faire de don, vous pouvez
+aussi proposer des patches!
+
+1.2) Démarrage rapide:
+---- ----------------
+IMPORTANT: Les instructions ci-dessous supposent que vous utilisez
+ScummVM en Français. Par défaut, ScummVM utilise la langue de votre
+système d'exploitation. Si vous préférez utiliser ScummVM en Anglais,
+vous pouvez plutôt utiliser le guide du fichier README Anglais.
+
+
+Pour les plus impatients, voici comment obtenir ScummVM en cinq étapes
+simples.
+
+1. Télécharger ScummVM sur <http://www.scummvm.org/downloads.php> et
+installer l'application.
+
+2. Créez un répertoire sur votre disque dur et copier les fichiers de
+données de jeu à partir du support original dans ce répertoire. Répétez
+cette opération pour chaque jeu que vous voulez jouer. Utilisez un
+répertoire séparé pour chaque jeu.
+
+3. Lancez ScummVM.
+
+Si ScummVM apparaît en anglais au lieu du français, procédez comme suit
+pour changer la langue:
+- Cliquez sur 'Options'.
+- Cliquez sur la flèche droite dans la barre d'onglets et sélectionnez
+ l'onglet 'Misc'.
+- Choisissez 'Francais' dans le champs 'GUI Language' et cliquez sur
+ 'OK'. Confirmez-le message qui apparaît, cliquez sur 'Quit' pour
+ quitter ScummVM, puis redémarrer le programme.
+
+Maintenant cliquez sur 'Ajouter...', puis sélectionnez le répertoire
+contenant les fichiers de données du jeu (ne pas essayer de sélectionner
+les fichiers de données eux-mêmes!) et cliquez sur 'Choisir'.
+
+4. Une boîte de dialogue devrait apparaître vous permettant de
+configurer divers paramètres si vous le souhaitez (la valeur par défaut
+devrait convenir dans la plupart des cas). Confirmez la boîte de
+dialogue.
+
+5. Sélectionnez le jeu que vous voulez jouer dans la liste, et appuyez
+sur 'Démarrer'.
+
+ScummVM se souvient des jeux ajoutés. Donc si vous quittez ScummVM puis
+le relancez la liste des jeux contiendra tous les jeux que vous avez
+déjà ajoutés. Vous pouvez donc passer directement à l'étape 5, à moins
+que vous vouliez ajouter des jeux supplémentaires.
+
+Astuce: Si vous souhaitez ajouter plusieurs jeux d'un coup, essayez
+d'appuyer et de maintenir la touche Maj (Shift) tout en cliquant sur
+'Ajouter...' - son texte changera en 'Ajout Massif…'. Vous serez alors
+invitez à sélectioner un répertoire dans lequel ScummVM parcourra tous
+les sous-répertoire à la recherche de jeux supportés.
+
+
+2.0) Contact:
+---- --------
+La meilleure façon de contacter l'équipe de ScummVM est en soumettant
+des rapports de bogues (voir section 2.1) ou en utilisant nos forums
+http://forums.scummvm.org. Vous pouvez également envoyer un e-mail sur
+la liste de diffusion scummvm-devel, ou discuter avec nous sur IRC
+(#scummvm sur irc.freenode.net). S'il vous plaît ne nous demandez pas de
+supporter un jeu non pris en charge - lire la FAQ sur notre site web
+avant. Notez que la langue officielle de la liste de diffusion, forum et
+chat est l'Anglais, et aucune autre langues ne doivent être utilisée.
+
+
+2.1) Reporting Bugs:
+---- ---------------
+Pour signaler un bogue, veuillez créer un compte SourceForge et suivez
+le lien "Bug Tracker" depuis notre page d'accueil. S'il vous plaît
+vérifiez que le bogue est reproductible, et se produit encore dans la
+'Daily Build' la plus récente. Vérifiez également la liste des problèmes
+connus (ci-dessous) et la liste de compatibilité sur notre site Web pour
+ce jeu, pour s'assurer que le problème n'est pas déjà connue:
+
+ http://www.scummvm.org/compatibility_stable.php
+
+Veuillez ne pas rapporter de bogues sur les jeux qui ne sont pas
+répertoriés comme étant finissable sur la liste de compatibilité. Nous
+savons que ces jeux ont des bogues.
+
+Veuillez inclure les informations suivantes lorsque vous signalez un
+problème:
+ - Version de ScummVM (veuillez tester avec la 'Daily Build' la plus
+ récente)
+ - Détails du problème, incluant les instructions pour le reproduire
+ - Langue du jeu (anglais, allemand, ...)
+ - Version du jeu (talkie, disquette, ...)
+ - Plate-forme et compilateur (Win32, Linux, Mac, FreeBSD, ...)
+ - Joindre une sauvegarde si possible
+ - Si ce problème est récent, s'il vous plaît notez la dernière
+ version sans bogue, et la première version qui à le problème. De
+ cette façon, nous pouvons y remédier plus rapidement, en regardant
+ les modifications apportées entre ces deux versions.
+
+Enfin, veuillez signaler chaque problème séparément, sinon, il devient
+difficile de suivre l'état de chaque problème individuel. S'il vous
+plaît gardez à l'esprit également que tous les rapports de bogue doivent
+être rédigés en anglais.
+
diff --git a/doc/translations/README-translation_template.txt b/doc/translations/README-translation_template.txt
new file mode 100755
index 0000000..ec43ebe
--- /dev/null
+++ b/doc/translations/README-translation_template.txt
@@ -0,0 +1,158 @@
+This document is a partial translation of the English README file. The
+original document has much more information, so if you cannot find what
+you need here and can understand a bit of English, try to look at the
+English README file.
+
+For more information, compatibility lists, details on donating, the
+latest release, progress reports and more, please visit the ScummVM home
+page at: http://www.scummvm.org/
+
+Table of Contents:
+------------------
+1.0) Introduction
+ * 1.1 About ScummVM
+ * 1.2 Quick start
+2.0) Contact
+ * 2.1 Reporting Bugs
+
+1.0) Introduction:
+---- -------------
+
+1.1) About ScummVM:
+---- --------------
+ScummVM is a program which allows you to run certain classic graphical
+point-and-click adventure games, provided you already have their data
+files. The clever part about this: ScummVM just replaces the executables
+shipped with the game, allowing you to play them on systems for which
+they were never designed!
+
+Originally it was designed to run LucasArts' SCUMM games, such as Maniac
+Mansion, Monkey Island, Day of the Tentacle or Sam and Max. SCUMM stands
+for 'Script Creation Utility for Maniac Mansion', which was the first
+game for which LucasArts designed this system. And much later it gave
+its name to ScummVM ('VM' meaning Virtual Machine).
+
+Over time support for a lot of non-SCUMM games has been added, and
+ScummVM now also supports many of Sierra's AGI and SCI games (such as
+King's Quest 1-6, Space Quest 1-5, ...), Discworld 1 and 2, Simon the
+Sorcerer 1 and 2, Beneath A Steel Sky, Lure of the Temptress, Broken
+Sword I and II, Flight of the Amazon Queen, Gobliiins 1-3, The Legend of
+Kyrandia series, many of Humongous Entertainment's children's SCUMM
+games (including Freddi Fish and Putt Putt games) and many more. You can
+find a full list with details on which adventures are supported and how
+well on the compatibility page. ScummVM is continually improving, so
+check back often.
+
+Among the systems on which you can play those games are regular desktop
+computers (running Windows, Linux, Mac OS X, ...), game consoles
+(Dreamcast, Nintendo DS & Wii, PS2, PSP, ...), smartphones (Android,
+iPhone, PocketPC, Symbian ...) and more.
+
+At this time ScummVM is still under heavy development. Be aware that
+whilst we attempt to make sure that many games can be completed with few
+major bugs, crashes can happen and we offer no warranty. That being
+said, some of the games have been supported for a long time and should
+work fine with any recent stable release. You can get a feeling of how
+well each game is working in ScummVM by looking at the compatibility
+page. Actually if you browse a bit around you might discover that
+ScummVM is even being used commercially to re-release some of the
+supported games on modern platforms. This shows that several companies
+are happy with the quality of the software and how well it can run some
+of the games.
+
+If you enjoy ScummVM feel free to donate using the PayPal button on the
+ScummVM homepage. This will help us buy utilities needed to develop
+ScummVM easier and quicker. If you cannot donate, help and contribute a
+patch!
+
+1.2) Quick start:
+---- ------------
+IMPORTANT: This short guide assumes you are using ScummVM in <translated
+language>. By default, ScummVM will use your operating system's
+language. If you prefer to use ScummVM in English, You may also prefer
+to follow the guide from the English REAMDE file.
+
+For the impatient among you, here is how to get ScummVM running in five
+simple steps.
+
+1. Download ScummVM from <http://www.scummvm.org/downloads.php> and
+install it.
+
+2. Create a directory on your hard drive and copy the game datafiles
+from the original media to this directory. Repeat this for every game
+you want to play (it is better to use a separate directory for each
+game).
+
+3. Start ScummVM.
+
+If at this stage ScummVM appears in English instead of <translated
+language>, do as follow to change the language:
+- Click on 'Options'.
+- Click on the right arrow in the tab bar and select the 'Misc' tab.
+- Select "<translated language>" in the 'GUI Language' box and click on
+ 'OK'.
+- Confirm the message box that pops-up, click on 'Quit' to quit ScummVM
+ and then restart the program.
+
+Now choose 'Add game', select the directory with the game datafiles (do
+not try to select the datafiles themselves!) and press 'Choose'
+
+4. A dialog should popup allowing you to configure various settings if
+you wish to (it should be just fine to leave everything at its default,
+though). Confirm the dialog.
+
+5. Select the game you want to play in the list, and press 'Start'.
+
+ScummVM remembers the games that you add. So if you close ScummVM, the
+next time you start it again the list of game will contain all the games
+you previously added. You can therefore go directly to step 5, unless
+you want to add more games.
+
+Hint: If you want to add multiple games in one go, try pressing and
+holding the shift key before clicking 'Add game' -- its label will
+change to 'Mass Add' and if you press it, you are again asked to select
+a directory, only this time ScummVM will search through all
+subdirectoriess for supported games.
+
+
+2.0) Contact:
+---- --------
+The easiest way to contact the ScummVM team is by submitting bug reports
+(see section 2.1) or by using our forums at http://forums.scummvm.org .
+You can also join and e-mail the scummvm-devel mailing list, or chat
+with us on IRC (#scummvm on irc.freenode.net) Please do not ask us to
+support an unsupported game -- read the FAQ on our web site first. Note
+that the official language of the forum, mailing list and chat is
+English and no other languages should be used.
+
+
+2.1) Reporting Bugs:
+---- ---------------
+To report a bug, please create a SourceForge account and follow the "Bug
+Tracker" link from our homepage. Please make sure the bug is
+reproducible, and still occurs in the latest SVN/Daily build version.
+Also check the known problems list (below) and the compatibility list on
+our website for that game, to ensure the issue is not already known:
+
+ http://www.scummvm.org/compatibility_stable.php
+
+Please do not report bugs on games that are not listed as being
+completeable in the 'Supported Games' section, or compatibility list. We
+-know- those games have bugs.
+
+Please include the following information:
+ - ScummVM version (PLEASE test the latest SVN/Daily build)
+ - Bug details, including instructions on reproducing
+ - Language of game (English, German, ...)
+ - Version of game (talkie, floppy, ...)
+ - Platform and Compiler (Win32, Linux, FreeBSD, ...)
+ - Attach a savegame if possible
+ - If this bug only occurred recently, please note the last version
+ without the bug, and the first version including the bug. That way
+ we can fix it quicker by looking at the changes made.
+
+Finally, please report each issue separately; do not file multiple
+issues on the same ticket. (Otherwise, it gets difficult to track the
+status of each individual bug). Please keep also in mind that all the
+bug reports must be written in English.
+
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index d273c2a..22d8adf 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -164,7 +164,7 @@ public:
AgiMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "AGI preAGI + v2 + v3 Engine";
+ return "AGI preAGI + v2 + v3";
}
virtual const char *getOriginalCopyright() const {
return "Sierra AGI Engine (C) Sierra On-Line Software";
diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp
index 2b7bf03..262798a 100644
--- a/engines/cine/detection.cpp
+++ b/engines/cine/detection.cpp
@@ -90,7 +90,7 @@ public:
CineMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Cinematique evo 1 engine";
+ return "Cinematique evo 1";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp
index d77d920..4aaaf03 100644
--- a/engines/cruise/detection.cpp
+++ b/engines/cruise/detection.cpp
@@ -247,7 +247,7 @@ public:
CruiseMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Cinematique evo 2 engine";
+ return "Cinematique evo 2";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp
index c3502cb..572ecce 100644
--- a/engines/draci/detection.cpp
+++ b/engines/draci/detection.cpp
@@ -113,7 +113,7 @@ public:
DraciMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Draci Historie Engine";
+ return "Draci Historie";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp
index 58a0549..5a8903d 100644
--- a/engines/drascula/detection.cpp
+++ b/engines/drascula/detection.cpp
@@ -296,7 +296,7 @@ public:
DrasculaMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Drascula Engine";
+ return "Drascula";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index c165090..be44c05 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -116,7 +116,7 @@ public:
GobMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Gob Engine";
+ return "Gob";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index bde89f8..78ecac8 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -219,7 +219,7 @@ public:
GroovieMetaEngine() : AdvancedMetaEngine(detectionParams) {}
const char *getName() const {
- return "Groovie Engine";
+ return "Groovie";
}
const char *getOriginalCopyright() const {
diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp
index 2fdb63d..25b8b16 100644
--- a/engines/hugo/detection.cpp
+++ b/engines/hugo/detection.cpp
@@ -161,7 +161,7 @@ public:
HugoMetaEngine() : AdvancedMetaEngine(detectionParams) {}
const char *getName() const {
- return "Hugo Engine";
+ return "Hugo";
}
const char *getOriginalCopyright() const {
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 3c59838..864228a 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -79,7 +79,7 @@ public:
KyraMetaEngine() : AdvancedMetaEngine(detectionParams) {}
const char *getName() const {
- return "Legend of Kyrandia Engine";
+ return "Legend of Kyrandia";
}
const char *getOriginalCopyright() const {
diff --git a/engines/lastexpress/detection.cpp b/engines/lastexpress/detection.cpp
index e55a6f6..bfcb415 100644
--- a/engines/lastexpress/detection.cpp
+++ b/engines/lastexpress/detection.cpp
@@ -207,7 +207,7 @@ public:
LastExpressMetaEngine() : AdvancedMetaEngine(detectionParams) {}
const char *getName() const {
- return "LastExpress Engine";
+ return "Last Express";
}
const char *getOriginalCopyright() const {
diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp
index b40e60a..a69300e 100644
--- a/engines/lure/detection.cpp
+++ b/engines/lure/detection.cpp
@@ -205,7 +205,7 @@ public:
LureMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Lure of the Temptress Engine";
+ return "Lure of the Temptress";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/m4/detection.cpp b/engines/m4/detection.cpp
index 645855a..1aefe3d 100644
--- a/engines/m4/detection.cpp
+++ b/engines/m4/detection.cpp
@@ -414,7 +414,7 @@ public:
M4MetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "MADS/M4 engine";
+ return "MADS/M4";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp
index e5a1176..4576e2b 100644
--- a/engines/made/detection.cpp
+++ b/engines/made/detection.cpp
@@ -555,7 +555,7 @@ public:
MadeMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "MADE Engine";
+ return "MADE";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index 3b7efe7..6a73b28 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -188,7 +188,7 @@ public:
MohawkMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Mohawk Engine";
+ return "Mohawk";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp
index 7e5798b..c3719bc 100644
--- a/engines/parallaction/detection.cpp
+++ b/engines/parallaction/detection.cpp
@@ -250,7 +250,7 @@ public:
ParallactionMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Parallaction engine";
+ return "Parallaction";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index ca52ff5..b23baf4 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -131,7 +131,7 @@ public:
SagaMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Saga engine ["
+ return "SAGA ["
#if defined(ENABLE_IHNM) && defined(ENABLE_SAGA2)
"all games"
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 28d6abb..61e6cc9 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -402,7 +402,7 @@ public:
SciMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "SCI Engine [SCI0, SCI01, SCI10, SCI11"
+ return "SCI [SCI0, SCI01, SCI10, SCI11"
#ifdef ENABLE_SCI32
", SCI32"
#endif
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index ec85f52..bba2696 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -1156,7 +1156,7 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co
}
const char *ScummMetaEngine::getName() const {
- return "SCUMM Engine ["
+ return "SCUMM ["
#if defined(ENABLE_SCUMM_7_8) && defined(ENABLE_HE)
"all games"
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp
index c17f914..fe23b88 100644
--- a/engines/scumm/imuse/imuse.cpp
+++ b/engines/scumm/imuse/imuse.cpp
@@ -926,7 +926,7 @@ void IMuseInternal::sequencer_timers(MidiDriver *midi) {
}
void IMuseInternal::handle_marker(uint id, byte data) {
- if (_queue_adding && _queue_sound == id && data == _queue_marker)
+ if ((_queue_end == _queue_pos) || (_queue_adding && _queue_sound == id && data == _queue_marker))
return;
uint16 *p = _cmd_queue[_queue_end].array;
@@ -937,7 +937,7 @@ void IMuseInternal::handle_marker(uint id, byte data) {
_queue_cleared = false;
_queue_end = (_queue_end + 1) % ARRAYSIZE(_cmd_queue);
- while(_queue_end != _queue_pos && _cmd_queue[_queue_end].array[0] == COMMAND_ID && !_queue_cleared) {
+ while (_queue_end != _queue_pos && _cmd_queue[_queue_end].array[0] == COMMAND_ID && !_queue_cleared) {
p = _cmd_queue[_queue_end].array;
doCommand_internal(p[1], p[2], p[3], p[4], p[5], p[6], p[7], 0);
_queue_end = (_queue_end + 1) % ARRAYSIZE(_cmd_queue);
diff --git a/engines/sword25/detection.cpp b/engines/sword25/detection.cpp
index 9ca44c6..caa1cf5 100644
--- a/engines/sword25/detection.cpp
+++ b/engines/sword25/detection.cpp
@@ -102,7 +102,7 @@ public:
Sword25MetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "The Broken Sword 2.5 Engine";
+ return "Broken Sword 2.5";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp
index 8db2b36..4784e2f 100644
--- a/engines/teenagent/detection.cpp
+++ b/engines/teenagent/detection.cpp
@@ -113,7 +113,7 @@ public:
}
virtual const char *getName() const {
- return "Teen Agent Engine";
+ return "Teen Agent";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index b0af9a9..27b16c5 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -104,7 +104,7 @@ public:
TinselMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Tinsel Engine";
+ return "Tinsel";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp
index f98d09a..1056f6e 100644
--- a/engines/toon/detection.cpp
+++ b/engines/toon/detection.cpp
@@ -147,7 +147,7 @@ public:
ToonMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Toon Engine";
+ return "Toon";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp
index 9d159e8..b7f9c09 100644
--- a/engines/touche/detection.cpp
+++ b/engines/touche/detection.cpp
@@ -156,7 +156,7 @@ public:
ToucheMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
- return "Touche Engine";
+ return "Touche";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp
index 2f05365..7534abd 100644
--- a/engines/tsage/core.cpp
+++ b/engines/tsage/core.cpp
@@ -3481,52 +3481,11 @@ void SceneHandler::postInit(SceneObjectList *OwnerList) {
void SceneHandler::process(Event &event) {
// Main keypress handler
- if ((event.eventType == EVENT_KEYPRESS) && !event.handled) {
- switch (event.kbd.keycode) {
- case Common::KEYCODE_F1:
- // F1 - Help
- MessageDialog::show((_vm->getFeatures() & GF_DEMO) ? DEMO_HELP_MSG : HELP_MSG, OK_BTN_STRING);
- break;
-
- case Common::KEYCODE_F2: {
- // F2 - Sound Options
- ConfigDialog *dlg = new ConfigDialog();
- dlg->runModal();
- delete dlg;
- _globals->_events.setCursorFromFlag();
- break;
- }
-
- case Common::KEYCODE_F3:
- // F3 - Quit
- _globals->_game->quitGame();
- event.handled = false;
- break;
-
- case Common::KEYCODE_F4:
- // F4 - Restart
- _globals->_game->restartGame();
- _globals->_events.setCursorFromFlag();
- break;
-
- case Common::KEYCODE_F7:
- // F7 - Restore
- _globals->_game->restoreGame();
- _globals->_events.setCursorFromFlag();
- break;
+ if (!event.handled) {
+ _globals->_game->processEvent(event);
- case Common::KEYCODE_F10:
- // F10 - Pause
- GfxDialog::setPalette();
- MessageDialog::show(GAME_PAUSED_MSG, OK_BTN_STRING);
+ if (event.eventType == EVENT_KEYPRESS)
_globals->_events.setCursorFromFlag();
- break;
-
- default:
- break;
- }
-
- _globals->_events.setCursorFromFlag();
}
// Check for displaying right-click dialog
diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp
index 4ab2142..20c2002 100644
--- a/engines/tsage/detection.cpp
+++ b/engines/tsage/detection.cpp
@@ -88,7 +88,7 @@ public:
}
virtual const char *getName() const {
- return "TsAGE Engine";
+ return "TsAGE";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/tsage/events.cpp b/engines/tsage/events.cpp
index 132225d..e889c56 100644
--- a/engines/tsage/events.cpp
+++ b/engines/tsage/events.cpp
@@ -151,8 +151,13 @@ void EventsClass::setCursor(CursorType cursorType) {
switch (cursorType) {
case CURSOR_NONE:
// No cursor
- cursor = _resourceManager->getSubResource(4, 1, 6, &size);
_globals->setFlag(122);
+
+ if (_vm->getFeatures() & GF_DEMO) {
+ CursorMan.showMouse(false);
+ return;
+ }
+ cursor = _resourceManager->getSubResource(4, 1, 6, &size);
break;
case CURSOR_LOOK:
diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp
index 5da00e8..85dfc5d 100644
--- a/engines/tsage/graphics.cpp
+++ b/engines/tsage/graphics.cpp
@@ -967,9 +967,10 @@ GfxButton *GfxDialog::execute(GfxButton *defaultButton) {
// Event loop
GfxButton *selectedButton = NULL;
- while (!_vm->getEventManager()->shouldQuit()) {
+ bool breakFlag = false;
+ while (!_vm->getEventManager()->shouldQuit() && !breakFlag) {
Event event;
- while (_globals->_events.getEvent(event)) {
+ while (_globals->_events.getEvent(event) && !breakFlag) {
// Adjust mouse positions to be relative within the dialog
event.mousePos.x -= _gfxManager._bounds.left;
event.mousePos.y -= _gfxManager._bounds.top;
@@ -978,19 +979,23 @@ GfxButton *GfxDialog::execute(GfxButton *defaultButton) {
if ((*i)->process(event))
selectedButton = static_cast<GfxButton *>(*i);
}
- }
- if (selectedButton)
- break;
- else if (!event.handled) {
- if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
- selectedButton = NULL;
- break;
- } else if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_RETURN)) {
- selectedButton = defaultButton;
+ if (selectedButton) {
+ breakFlag = true;
break;
+ } else if (!event.handled) {
+ if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
+ selectedButton = NULL;
+ breakFlag = true;
+ break;
+ } else if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_RETURN)) {
+ selectedButton = defaultButton;
+ breakFlag = true;
+ break;
+ }
}
}
+
g_system->delayMillis(10);
g_system->updateScreen();
}
diff --git a/engines/tsage/ringworld_demo.cpp b/engines/tsage/ringworld_demo.cpp
index 2dacea6..3ad414f 100644
--- a/engines/tsage/ringworld_demo.cpp
+++ b/engines/tsage/ringworld_demo.cpp
@@ -39,6 +39,68 @@ Scene *RingworldDemoGame::createScene(int sceneNumber) {
return new RingworldDemoScene();
}
+void RingworldDemoGame::quitGame() {
+ _globals->_events.setCursor(CURSOR_ARROW);
+ MessageDialog *dlg = new MessageDialog(DEMO_EXIT_MSG, EXIT_BTN_STRING, DEMO_BTN_STRING);
+ dlg->draw();
+
+ GfxButton *selectedButton = dlg->execute(&dlg->_btn2);
+ bool exitFlag = selectedButton != &dlg->_btn2;
+
+ delete dlg;
+ _globals->_events.hideCursor();
+
+ if (exitFlag)
+ _vm->quitGame();
+}
+
+void RingworldDemoGame::pauseGame() {
+ _globals->_events.setCursor(CURSOR_ARROW);
+ MessageDialog *dlg = new MessageDialog(DEMO_PAUSED_MSG, EXIT_BTN_STRING, DEMO_RESUME_BTN_STRING);
+ dlg->draw();
+
+ GfxButton *selectedButton = dlg->execute(&dlg->_btn2);
+ bool exitFlag = selectedButton != &dlg->_btn2;
+
+ delete dlg;
+ _globals->_events.hideCursor();
+
+ if (exitFlag)
+ _vm->quitGame();
+}
+
+void RingworldDemoGame::processEvent(Event &event) {
+ if (event.eventType == EVENT_KEYPRESS) {
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_F1:
+ // F1 - Help
+ MessageDialog::show(DEMO_HELP_MSG, OK_BTN_STRING);
+ break;
+
+ case Common::KEYCODE_F2: {
+ // F2 - Sound Options
+ ConfigDialog *dlg = new ConfigDialog();
+ dlg->runModal();
+ delete dlg;
+ _globals->_events.setCursorFromFlag();
+ break;
+ }
+
+ case Common::KEYCODE_F3:
+ // F3 - Quit
+ quitGame();
+ event.handled = false;
+ break;
+
+ default:
+ break;
+ }
+ } else if (event.eventType == EVENT_BUTTON_DOWN) {
+ pauseGame();
+ event.handled = true;
+ }
+}
+
/*--------------------------------------------------------------------------
* Ringworld Demo scene
*
diff --git a/engines/tsage/ringworld_demo.h b/engines/tsage/ringworld_demo.h
index 8b69da8..7492c1e 100644
--- a/engines/tsage/ringworld_demo.h
+++ b/engines/tsage/ringworld_demo.h
@@ -32,9 +32,13 @@
namespace tSage {
class RingworldDemoGame: public Game {
+private:
+ void pauseGame();
public:
virtual void start();
virtual Scene *createScene(int sceneNumber);
+ virtual void quitGame();
+ virtual void processEvent(Event &event);
};
class RingworldDemoScene: public Scene {
diff --git a/engines/tsage/ringworld_logic.cpp b/engines/tsage/ringworld_logic.cpp
index a03c408..2141fcc 100644
--- a/engines/tsage/ringworld_logic.cpp
+++ b/engines/tsage/ringworld_logic.cpp
@@ -1421,4 +1421,52 @@ void RingworldGame::endGame(int resNum, int lineNum) {
_globals->_events.setCursorFromFlag();
}
+void RingworldGame::processEvent(Event &event) {
+ if (event.eventType == EVENT_KEYPRESS) {
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_F1:
+ // F1 - Help
+ MessageDialog::show(HELP_MSG, OK_BTN_STRING);
+ break;
+
+ case Common::KEYCODE_F2: {
+ // F2 - Sound Options
+ ConfigDialog *dlg = new ConfigDialog();
+ dlg->runModal();
+ delete dlg;
+ _globals->_events.setCursorFromFlag();
+ break;
+ }
+
+ case Common::KEYCODE_F3:
+ // F3 - Quit
+ quitGame();
+ event.handled = false;
+ break;
+
+ case Common::KEYCODE_F4:
+ // F4 - Restart
+ restartGame();
+ _globals->_events.setCursorFromFlag();
+ break;
+
+ case Common::KEYCODE_F7:
+ // F7 - Restore
+ restoreGame();
+ _globals->_events.setCursorFromFlag();
+ break;
+
+ case Common::KEYCODE_F10:
+ // F10 - Pause
+ GfxDialog::setPalette();
+ MessageDialog::show(GAME_PAUSED_MSG, OK_BTN_STRING);
+ _globals->_events.setCursorFromFlag();
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
} // End of namespace tSage
diff --git a/engines/tsage/ringworld_logic.h b/engines/tsage/ringworld_logic.h
index 6fa92fa..19b0f10 100644
--- a/engines/tsage/ringworld_logic.h
+++ b/engines/tsage/ringworld_logic.h
@@ -453,6 +453,7 @@ public:
virtual void endGame(int resNum, int lineNum);
virtual Scene *createScene(int sceneNumber);
+ virtual void processEvent(Event &event);
};
} // End of namespace tSage
diff --git a/engines/tsage/ringworld_scenes2.cpp b/engines/tsage/ringworld_scenes2.cpp
index 906f648..4378eac 100644
--- a/engines/tsage/ringworld_scenes2.cpp
+++ b/engines/tsage/ringworld_scenes2.cpp
@@ -477,13 +477,14 @@ void Scene1001::Action1::signal() {
case 19: {
_globals->_soundHandler.startSound(91);
byte adjustData[4] = {0xff, 0xff, 0xff, 0};
- _globals->_scenePalette.fade(adjustData, true, 0);
+ _globals->_scenePalette.fade(adjustData, false, 0);
scene->_object1._strip = 7;
scene->_object1._frame = 1;
scene->_object1.setPosition(Common::Point(314, 112));
scene->_object1.addMover(NULL);
setDelay(2);
+ break;
}
case 20:
_globals->_scenePalette.loadPalette(16);
diff --git a/engines/tsage/scenes.h b/engines/tsage/scenes.h
index a5aacba..b3c009c 100644
--- a/engines/tsage/scenes.h
+++ b/engines/tsage/scenes.h
@@ -129,6 +129,7 @@ public:
virtual void quitGame() {}
virtual void endGame(int resNum, int lineNum) {}
virtual Scene *createScene(int sceneNumber) = 0;
+ virtual void processEvent(Event &event) {}
};
} // End of namespace tSage
diff --git a/engines/tsage/staticres.cpp b/engines/tsage/staticres.cpp
index 6c2d924..9f36268 100644
--- a/engines/tsage/staticres.cpp
+++ b/engines/tsage/staticres.cpp
@@ -112,6 +112,10 @@ const char *SCENE6100_VERY_WELL = "Very well. I will retrieve the stasis box and
Wait for it's return in the lander bay.";
const char *DEMO_HELP_MSG = " Help...\rF2 - Sound Options\rF3 - Exit demo\r\rPress ENTER\rto continue";
-const char *DEMO_PAUSED_MSG = " demo is paused";
+const char *DEMO_PAUSED_MSG = "Ringworld\x14 demo is paused";
+const char *DEMO_EXIT_MSG = "Press ENTER to resume the Ringworld\x14 demo. Press ESC to exit";
+const char *EXIT_BTN_STRING = "Exit";
+const char *DEMO_BTN_STRING = "Demo";
+const char *DEMO_RESUME_BTN_STRING = "Resume";
} // End of namespace tSage
diff --git a/engines/tsage/staticres.h b/engines/tsage/staticres.h
index bed9e0d..fa93511 100644
--- a/engines/tsage/staticres.h
+++ b/engines/tsage/staticres.h
@@ -79,6 +79,12 @@ extern const char *SCENE6100_VERY_WELL;
// Demo messages
extern const char *DEMO_HELP_MSG;
extern const char *DEMO_PAUSED_MSG;
+extern const char *DEMO_HELP_MSG;
+extern const char *DEMO_PAUSED_MSG;
+extern const char *DEMO_EXIT_MSG;
+extern const char *EXIT_BTN_STRING;
+extern const char *DEMO_BTN_STRING;
+extern const char *DEMO_RESUME_BTN_STRING;
} // End of namespace tSage
diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp
index 89b0b87..9b466d6 100644
--- a/engines/tucker/detection.cpp
+++ b/engines/tucker/detection.cpp
@@ -143,7 +143,7 @@ public:
}
virtual const char *getName() const {
- return "Tucker Engine";
+ return "Tucker";
}
virtual const char *getOriginalCopyright() const {
diff --git a/gui/credits.h b/gui/credits.h
index 7ad4800..f8e9390 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -59,7 +59,7 @@ static const char *credits[] = {
"C0""Ludvig Strigeus",
"C2""(retired)",
"",
-"C1""BASS",
+"C1""Beneath a Steel Sky",
"C0""Robert G\366ffringmann",
"C2""(retired)",
"C0""Oliver Kiehl",
@@ -101,7 +101,7 @@ static const char *credits[] = {
"C0""Vincent Hamm",
"C2""(retired)",
"",
-"C1""Draci",
+"C1""Draci Historie",
"C0""Denis Kasak",
"C0""Robert Spalek",
"",
@@ -109,7 +109,7 @@ static const char *credits[] = {
"C0""Filippos Karapetis",
"C0""Pawel Kolodziejski",
"",
-"C1""FOTAQ",
+"C1""Flight of the Amazon Queen",
"C0""David Eriksson",
"C2""(retired)",
"C0""Gregory Montoir",
@@ -131,7 +131,7 @@ static const char *credits[] = {
"C0""Oystein Eftevaag",
"C0""Eugene Sandulenko",
"",
-"C1""Kyra",
+"C1""Legend of Kyrandia",
"C0""Torbj\366rn Andersson",
"C2""VQA Player",
"C0""Oystein Eftevaag",
@@ -144,7 +144,7 @@ static const char *credits[] = {
"C0""Jordi Vilalta Prat",
"C0""Julien Templier",
"",
-"C1""Lure",
+"C1""Lure of the Temptress",
"C0""Paul Gilbert",
"",
"C1""M4",
@@ -185,7 +185,7 @@ static const char *credits[] = {
"C0""Jordi Vilalta Prat",
"C0""Lars Skovlund",
"",
-"C1""TeenAgent",
+"C1""Teen Agent",
"C0""Robert Megone",
"C2""Help with callback rewriting",
"C0""Vladimir Menshakov",
diff --git a/gui/options.cpp b/gui/options.cpp
index d350139..e42d6c6 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -305,8 +305,14 @@ void OptionsDialog::close() {
if (getResult()) {
// Graphic options
+ bool graphicsModeChanged = false;
if (_fullscreenCheckbox) {
if (_enableGraphicSettings) {
+ if (ConfMan.getBool("fullscreen", _domain) != _fullscreenCheckbox->getState())
+ graphicsModeChanged = true;
+ if (ConfMan.getBool("aspect_ratio", _domain) != _aspectCheckbox->getState())
+ graphicsModeChanged = true;
+
ConfMan.setBool("fullscreen", _fullscreenCheckbox->getState(), _domain);
ConfMan.setBool("aspect_ratio", _aspectCheckbox->getState(), _domain);
ConfMan.setBool("disable_dithering", _disableDitheringCheckbox->getState(), _domain);
@@ -318,6 +324,8 @@ void OptionsDialog::close() {
while (gm->name) {
if (gm->id == (int)_gfxPopUp->getSelectedTag()) {
+ if (ConfMan.get("gfx_mode", _domain) != gm->name)
+ graphicsModeChanged = true;
ConfMan.set("gfx_mode", gm->name, _domain);
isSet = true;
break;
@@ -338,6 +346,48 @@ void OptionsDialog::close() {
ConfMan.removeKey("render_mode", _domain);
}
}
+
+ // Setup graphics again if needed
+ if (_domain == Common::ConfigManager::kApplicationDomain && graphicsModeChanged) {
+ g_system->beginGFXTransaction();
+ g_system->setGraphicsMode(ConfMan.get("gfx_mode", _domain).c_str());
+
+ if (ConfMan.hasKey("aspect_ratio"))
+ g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, ConfMan.getBool("aspect_ratio", _domain));
+ if (ConfMan.hasKey("fullscreen"))
+ g_system->setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen", _domain));
+ OSystem::TransactionError gfxError = g_system->endGFXTransaction();
+ if (gfxError != OSystem::kTransactionSuccess) {
+ // Revert ConfMan to what OSystem is using.
+ Common::String message = "Failed to apply some of the graphic options changes:";
+
+ if (gfxError & OSystem::kTransactionModeSwitchFailed) {
+ const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes();
+ while (gm->name) {
+ if (gm->id == g_system->getGraphicsMode()) {
+ ConfMan.set("gfx_mode", gm->name, _domain);
+ break;
+ }
+ gm++;
+ }
+ message += "\nthe video mode could not be changed.";
+ }
+
+ if (gfxError & OSystem::kTransactionAspectRatioFailed) {
+ ConfMan.setBool("aspect_ratio", g_system->getFeatureState(OSystem::kFeatureAspectRatioCorrection), _domain);
+ message += "\nthe fullscreen setting could not be changed";
+ }
+
+ if (gfxError & OSystem::kTransactionFullscreenFailed) {
+ ConfMan.setBool("fullscreen", g_system->getFeatureState(OSystem::kFeatureFullscreenMode), _domain);
+ message += "\nthe aspect ratio setting could not be changed";
+ }
+
+ // And display the error
+ GUI::MessageDialog dialog(message);
+ dialog.runModal();
+ }
+ }
// Volume options
if (_musicVolumeSlider) {
diff --git a/test/common/array.h b/test/common/array.h
index f17edd3..c102704 100644
--- a/test/common/array.h
+++ b/test/common/array.h
@@ -107,6 +107,34 @@ class ArrayTestSuite : public CxxTest::TestSuite
}
+ void test_self_insert() {
+ Common::Array<int> array;
+ int i;
+
+ // Insert some data -- and make sure we have enough space for
+ // *twice* as much data. This way, there is no need to allocate
+ // new storage, so if the insert() operation is "clever", it
+ // will try to reuse the existing storage.
+ // This in turn may uncover bugs if the insertion code does not
+ // expect self-insertions.
+ array.reserve(128);
+ for (i = 0; i < 64; ++i)
+ array.push_back(i);
+
+ // Now insert the array into the middle of itself
+ array.insert_at(12, array);
+
+ // Verify integrity
+ TS_ASSERT_EQUALS(array.size(), 128UL);
+
+ for (i = 0; i < 12; ++i)
+ TS_ASSERT_EQUALS(array[i], i);
+ for (i = 0; i < 64; ++i)
+ TS_ASSERT_EQUALS(array[i+12], i);
+ for (i = 12; i < 64; ++i)
+ TS_ASSERT_EQUALS(array[i+64], i);
+ }
+
void test_remove_at() {
Common::Array<int> array;
diff --git a/test/module.mk b/test/module.mk
index 3542ae2..4e5cbf6 100644
--- a/test/module.mk
+++ b/test/module.mk
@@ -9,7 +9,7 @@ TESTS := $(srcdir)/test/common/*.h $(srcdir)/test/audio/*.h
TEST_LIBS := audio/libaudio.a common/libcommon.a
#
-TEST_FLAGS := --runner=StdioPrinter
+TEST_FLAGS := --runner=StdioPrinter --no-std --no-eh
TEST_CFLAGS := -I$(srcdir)/test/cxxtest
TEST_LDFLAGS := $(LIBS)
TEST_CXXFLAGS := $(filter-out -Wglobal-constructors,$(CXXFLAGS))
Commit: b4d59f9ce50fe9db0ac64d22edb4e1c3451abff0
https://github.com/scummvm/scummvm/commit/b4d59f9ce50fe9db0ac64d22edb4e1c3451abff0
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:16-07:00
Commit Message:
FM-TOWNS AUDIO: some more midi driver code for FM-TOWNS versions of monkey2 and indy4
Changed paths:
A audio/softsynth/fmtowns_pc98/towns_midi.cpp
A audio/softsynth/fmtowns_pc98/towns_midi.h
A audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
R audio/softsynth/ym2612.cpp
R audio/softsynth/ym2612.h
audio/module.mk
engines/scumm/player_towns.cpp
engines/scumm/player_towns.h
engines/scumm/scumm.cpp
diff --git a/audio/module.mk b/audio/module.mk
index a9d9bfc..840b6d6 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -39,10 +39,11 @@ MODULE_OBJS := \
softsynth/opl/mame.o \
softsynth/fmtowns_pc98/towns_audio.o \
softsynth/fmtowns_pc98/towns_euphony.o \
+ softsynth/fmtowns_pc98/towns_midi.o \
softsynth/fmtowns_pc98/towns_pc98_driver.o \
softsynth/fmtowns_pc98/towns_pc98_fmsynth.o \
+ softsynth/fmtowns_pc98/towns_pc98_plugins.o \
softsynth/appleiigs.o \
- softsynth/ym2612.o \
softsynth/fluidsynth.o \
softsynth/mt32.o \
softsynth/eas.o \
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
new file mode 100644
index 0000000..8bf6d11
--- /dev/null
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -0,0 +1,238 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: $
+ * $Id: $
+ */
+
+#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
+
+class MidiChannel_TOWNS : public MidiChannel {
+public:
+ MidiChannel_TOWNS(MidiDriver_TOWNS *driver);
+ ~MidiChannel_TOWNS();
+
+ MidiDriver *device() { return _driver; }
+ byte getNumber() { return 0; }
+ void release();
+
+ void send(uint32 b);
+
+ void noteOff(byte note);
+ void noteOn(byte note, byte velocity);
+ void programChange(byte program);
+ void pitchBend(int16 bend);
+ void controlChange(byte control, byte value);
+ void pitchBendFactor(byte value);
+ void priority(byte value);
+
+ void sysEx_customInstrument(uint32 type, const byte *instr);
+
+private:
+ MidiDriver_TOWNS *_driver;
+};
+
+MidiChannel_TOWNS::MidiChannel_TOWNS(MidiDriver_TOWNS *driver) : MidiChannel(), _driver(driver) {
+
+}
+
+MidiChannel_TOWNS::~MidiChannel_TOWNS() {
+
+}
+
+void MidiChannel_TOWNS::release() {
+
+}
+
+void MidiChannel_TOWNS::send(uint32 b) {
+
+}
+
+void MidiChannel_TOWNS::noteOff(byte note) {
+
+}
+
+void MidiChannel_TOWNS::noteOn(byte note, byte velocity) {
+
+}
+
+void MidiChannel_TOWNS::programChange(byte program) {
+
+}
+
+void MidiChannel_TOWNS::pitchBend(int16 bend) {
+
+}
+
+void MidiChannel_TOWNS::controlChange(byte control, byte value) {
+
+}
+
+void MidiChannel_TOWNS::pitchBendFactor(byte value) {
+
+}
+
+void MidiChannel_TOWNS::priority(byte value) {
+
+}
+
+void MidiChannel_TOWNS::sysEx_customInstrument(uint32 type, const byte *instr) {
+
+}
+
+MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timerBpara(0), _open(false) {
+ _intf = new TownsAudioInterface(mixer, this);
+ _channels = new MidiChannel_TOWNS*[16];
+ for (int i = 0; i < 16; i++)
+ _channels[i] = new MidiChannel_TOWNS(this);
+
+ _tickCounter = 0;
+ _curChan = 0;
+ //unbuffered write: _intf->callback(17, part, reg, val);
+ //buffered write: _intf->callback(19, part, reg, val);
+}
+
+MidiDriver_TOWNS::~MidiDriver_TOWNS() {
+ close();
+ delete _intf;
+ setTimerCallback(0, 0);
+
+ for (int i = 0; i < 16; i++)
+ delete _channels[i];
+ delete[] _channels;
+}
+
+int MidiDriver_TOWNS::open() {
+ if (_open)
+ return MERR_ALREADY_OPEN;
+
+ if (!_intf->init())
+ return MERR_CANNOT_CONNECT;
+
+ _intf->callback(0);
+
+ _intf->callback(21, 255, 1);
+ _intf->callback(21, 0, 1);
+ _intf->callback(22, 255, 221);
+
+ _intf->callback(33, 8);
+ _intf->setSoundEffectChanMask(~0x3f);
+
+ _open = true;
+
+ return 0;
+}
+
+void MidiDriver_TOWNS::close() {
+ _open = false;
+}
+
+void MidiDriver_TOWNS::send(uint32 b) {
+ byte param2 = (b >> 16) & 0xFF;
+ byte param1 = (b >> 8) & 0xFF;
+ byte cmd = b & 0xF0;
+
+ /*AdLibPart *part;
+ if (chan == 9)
+ part = &_percussion;
+ else**/
+ MidiChannel_TOWNS *c = _channels[b & 0x0F];
+
+ switch (cmd) {
+ case 0x80:
+ //part->noteOff(param1);
+ break;
+ case 0x90:
+ //part->noteOn(param1, param2);
+ if (param2)
+ c->noteOn(param1, param2);
+ else
+ c->noteOff(param1);
+ break;
+ case 0xB0:
+ // supported: 1, 7, 0x40
+ c->controlChange(param1, param2);
+ break;
+ case 0xC0:
+ c->programChange(param1);
+ break;
+ case 0xE0:
+ //part->pitchBend((param1 | (param2 << 7)) - 0x2000);
+ c->pitchBend((param1 | (param2 << 7)) - 0x2000);
+ break;
+ case 0xF0:
+ warning("MidiDriver_ADLIB: Receiving SysEx command on a send() call");
+ break;
+
+ default:
+ break;
+ }
+}
+
+void MidiDriver_TOWNS::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
+ _timerBproc = timer_proc;
+ _timerBpara = timer_param;
+}
+
+uint32 MidiDriver_TOWNS::getBaseTempo() {
+ return 0;
+}
+
+MidiChannel *MidiDriver_TOWNS::allocateChannel() {
+ MidiChannel *res = 0;
+
+ for (int i = 0; i < 6; i++) {
+ if (++_curChan == 6)
+ _curChan = 0;
+
+ //if (_channels[i]-> //// )
+ // return _channels[i];
+
+ }
+
+ //if (res)
+ // res->noteOff();
+
+ return res;
+}
+
+MidiChannel *MidiDriver_TOWNS::getPercussionChannel() {
+ return 0;
+}
+
+void MidiDriver_TOWNS::timerCallback(int timerId) {
+ if (!_open)
+ return;
+
+ switch (timerId) {
+ case 1:
+ if (_timerBproc) {
+ _timerBproc(_timerBpara);
+ _tickCounter += 10000;
+ while (_tickCounter >= 4167) {
+ _tickCounter -= 4167;
+ //_timerBproc(_timerBpara);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
new file mode 100644
index 0000000..658c5a4
--- /dev/null
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: $
+ * $Id: $
+ */
+
+#ifndef TOWNS_MIDI_H
+#define TOWNS_MIDI_H
+
+#include "audio/mididrv.h"
+#include "audio/softsynth/fmtowns_pc98/towns_audio.h"
+
+class MidiChannel_TOWNS;
+class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver {
+friend class MidiChannel_TOWNS;
+public:
+ MidiDriver_TOWNS(Audio::Mixer *mixer);
+ ~MidiDriver_TOWNS();
+
+ int open();
+ bool isOpen() const { return _open; }
+ void close();
+ void send(uint32 b);
+ //virtual uint32 property(int prop, uint32 param) { return 0; }
+ //virtual void sysEx(const byte *msg, uint16 length) { }
+ //virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { }
+ //virtual void metaEvent(byte type, byte *data, uint16 length) { }
+ void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
+ uint32 getBaseTempo();
+ MidiChannel *allocateChannel();
+ MidiChannel *getPercussionChannel();
+
+ void timerCallback(int timerId);
+
+ TownsAudioInterface *intf() { return _intf; }
+
+private:
+ MidiChannel_TOWNS **_channels;
+
+ Common::TimerManager::TimerProc _timerBproc;
+ void *_timerBpara;
+
+ TownsAudioInterface *_intf;
+
+ uint32 _tickCounter;
+ uint8 _curChan;
+
+ bool _open;
+};
+
+#endif
+
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
new file mode 100644
index 0000000..e4b3723
--- /dev/null
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: $
+ * $Id: $
+ */
+
+#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
+#include "audio/musicplugin.h"
+#include "common/translation.h"
+
+
+class TownsEmuMusicPlugin : public MusicPluginObject {
+public:
+ const char *getName() const {
+ return _s("FM-Towns Audio");
+ }
+
+ const char *getId() const {
+ return "towns";
+ }
+
+ MusicDevices getDevices() const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
+};
+
+MusicDevices TownsEmuMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ devices.push_back(MusicDevice(this, "", MT_TOWNS));
+ return devices;
+}
+
+Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
+ *mididriver = new MidiDriver_TOWNS(g_system->getMixer());
+ return Common::kNoError;
+}
+
+class PC98EmuMusicPlugin : public MusicPluginObject {
+public:
+ const char *getName() const {
+ return _s("PC-98 Audio");
+ }
+
+ const char *getId() const {
+ return "pc98";
+ }
+
+ MusicDevices getDevices() const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
+};
+
+MusicDevices PC98EmuMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ devices.push_back(MusicDevice(this, "", MT_PC98));
+ return devices;
+}
+
+Common::Error PC98EmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
+ //*mididriver = /**/
+ return Common::kNoError;
+}
+
+//#if PLUGIN_ENABLED_DYNAMIC(TOWNS)
+ //REGISTER_PLUGIN_DYNAMIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin);
+ //REGISTER_PLUGIN_DYNAMIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin);
+//#else
+ REGISTER_PLUGIN_STATIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin);
+ REGISTER_PLUGIN_STATIC(PC98, PLUGIN_TYPE_MUSIC, PC98EmuMusicPlugin);
+//#endif
diff --git a/audio/softsynth/ym2612.cpp b/audio/softsynth/ym2612.cpp
deleted file mode 100644
index d966595..0000000
--- a/audio/softsynth/ym2612.cpp
+++ /dev/null
@@ -1,790 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <math.h>
-
-#include "audio/softsynth/ym2612.h"
-#include "common/util.h"
-#include "audio/musicplugin.h"
-#include "common/error.h"
-#include "common/system.h"
-#include "common/textconsole.h"
-#include "common/translation.h"
-#include "common/types.h"
-
-////////////////////////////////////////
-//
-// Miscellaneous
-//
-////////////////////////////////////////
-
-static int *sintbl = 0;
-static int *powtbl = 0;
-static int *frequencyTable = 0;
-static int *keycodeTable = 0;
-static int *keyscaleTable = 0;
-static int *attackOut = 0;
-
-
-////////////////////////////////////////
-//
-// Operator2612 implementation
-//
-////////////////////////////////////////
-
-Operator2612::Operator2612 (Voice2612 *owner) :
- _owner (owner),
- _state (_s_ready),
- _currentLevel ((int32)0x7f << 15),
- _phase (0),
- _lastOutput (0),
- _feedbackLevel (0),
- _detune (0),
- _multiple (1),
- _keyScale (0),
- _specifiedTotalLevel (127),
- _specifiedAttackRate (0),
- _specifiedDecayRate (0),
- _specifiedSustainRate (0),
- _specifiedReleaseRate (15) {
- velocity(0);
-}
-
-Operator2612::~Operator2612()
-{ }
-
-void Operator2612::velocity(int velo) {
- _velocity = velo;
- _totalLevel = ((int32)_specifiedTotalLevel << 15) +
- ((int32)(127-_velocity) << 13);
- _sustainLevel = ((int32)_specifiedSustainLevel << 17);
-}
-
-void Operator2612::feedbackLevel(int level) {
- _feedbackLevel = level;
-}
-
-void Operator2612::setInstrument(byte const *instrument) {
- _detune = (instrument[8] >> 4) & 7;
- _multiple = instrument[8] & 15;
- _specifiedTotalLevel = instrument[12] & 127;
- _keyScale = (instrument[16] >> 6) & 3;
- _specifiedAttackRate = instrument[16] & 31;
- _specifiedDecayRate = instrument[20] & 31;
- _specifiedSustainRate = instrument[24] & 31;
- _specifiedSustainLevel = (instrument[28] >> 4) & 15;
- _specifiedReleaseRate = instrument[28] & 15;
- _state = _s_ready;
- velocity(_velocity);
-}
-
-void Operator2612::keyOn() {
- _state = _s_attacking;
- _tickCount = 0;
- _phase = 0;
- _currentLevel = ((int32)0x7f << 15);
-}
-
-void Operator2612::keyOff() {
- if (_state != _s_ready)
- _state = _s_releasing;
-}
-
-void Operator2612::frequency(int freq) {
- double value; // Use for intermediate computations to avoid int64 arithmetic
- int r;
-
- _frequency = freq / _owner->_rate;
-
- r = _specifiedAttackRate;
- if (r != 0) {
- r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
- if (r >= 64)
- r = 63;
- }
-
- r = 63 - r;
- if (_specifiedTotalLevel >= 128)
- value = 0;
- else {
- value = powtbl[(r&3) << 7];
- value *= 1 << (r >> 2);
- value *= 41;
- value /= 1 << (15 + 5);
- value *= 127 - _specifiedTotalLevel;
- value /= 127;
- }
- _attackTime = (int32) value; // 1 ?? == (1 << 12)
- if (_attackTime > 0)
- _attackTime = (1 << (12+10)) / (_owner->_rate * _attackTime);
-
- r = _specifiedDecayRate;
- if (r != 0) {
- r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
- if (r >= 64)
- r = 63;
- }
- value = (double) powtbl[(r&3) << 7] * (0x10 << (r>>2)) / 31;
- _decayRate = (int32) value / _owner->_rate;
-
- r = _specifiedSustainRate;
- if (r != 0) {
- r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
- if (r >= 64)
- r = 63;
- }
- value = (double) powtbl[(r&3) << 7] * (0x10 << (r>>2)) / 31;
- _sustainRate = (int32) value / _owner->_rate;
-
- r = _specifiedReleaseRate;
- if (r != 0) {
- r = r * 2 + 1; // (Translated) I cannot know whether the timing is a good choice or not
- r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
- // KS
- if (r >= 64)
- r = 63;
- }
- value = (double) powtbl[(r&3) << 7] * (0x10 << (r>>2)) / 31;
- _releaseRate = (int32) value / _owner->_rate;
-}
-
-void Operator2612::nextTick(const int *phasebuf, int *outbuf, int buflen) {
- if (_state == _s_ready)
- return;
- if (_state == _s_attacking && _attackTime <= 0) {
- _currentLevel = 0;
- _state = _s_decaying;
- }
-
- int32 levelIncrement = 0;
- int32 target = 0;
- State next_state = _s_ready;
- const int32 zero_level = ((int32)0x7f << 15);
- const int phaseIncrement = (_multiple > 0) ? (_frequency * _multiple) : (_frequency / 2);
-
- int32 output = _lastOutput;
- int32 level = _currentLevel + _totalLevel;
-
- while (buflen) {
- switch (_state) {
- case _s_ready:
- return;
- case _s_attacking:
- next_state = _s_attacking;
- break;
- case _s_decaying:
- levelIncrement = _decayRate;
- target = _sustainLevel + _totalLevel;
- next_state = _s_sustaining;
- break;
- case _s_sustaining:
- levelIncrement = _sustainRate;
- target = zero_level + _totalLevel;
- next_state = _s_ready;
- break;
- case _s_releasing:
- levelIncrement = _releaseRate;
- target = zero_level + _totalLevel;
- next_state = _s_ready;
- break;
- }
-
- bool switching = false;
- do {
- if (next_state == _s_attacking) {
- // Attack phase
- ++_tickCount;
- int i = (int) (_tickCount * _attackTime);
- if (i >= 1024) {
- level = _totalLevel;
- _state = _s_decaying;
- switching = true;
- } else {
- level = (attackOut[i] << (31 - 8 - 16)) + _totalLevel;
- }
- } else {
- // Decay, Sustain and Release phases
- level += levelIncrement;
- if (level >= target) {
- level = target;
- _state = next_state;
- switching = true;
- }
- }
-
- if (level < zero_level) {
- int phaseShift = *phasebuf >> 2;
- if (_feedbackLevel)
- phaseShift += (output << (_feedbackLevel - 1)) / 1024;
- output = sintbl[((_phase >> 7) + phaseShift) & 0x7ff];
- output >>= (level >> 18);
- // Here is the original code, which requires 64-bit ints
-// output *= powtbl[511 - ((level>>25)&511)];
-// output >>= 16;
-// output >>= 1;
- // And here's our 32-bit trick for doing it. (Props to Fingolfin!)
- // Result varies from original code by max of 1.
-// int powVal = powtbl[511 - ((level>>9)&511)];
-// int outputHI = output / 256;
-// int powHI = powVal / 256;
-// output = (outputHI * powHI) / 2 + (outputHI * (powVal % 256) + powHI * (output % 256)) / 512;
- // And here's the even faster code.
- // Result varies from original code by max of 8.
- output = ((output >> 4) * (powtbl[511-((level>>9)&511)] >> 3)) / 1024;
-
- _phase += phaseIncrement;
- _phase &= 0x3ffff;
- } else
- output = 0;
-
- *outbuf += output;
- --buflen;
- ++phasebuf;
- ++outbuf;
- } while (buflen && !switching);
- }
- _lastOutput = output;
- _currentLevel = level - _totalLevel;
-}
-
-////////////////////////////////////////
-//
-// Voice2612 implementation
-//
-////////////////////////////////////////
-
-Voice2612::Voice2612() {
- next = 0;
- _control7 = 127;
- _note = 40;
- _frequency = 440;
- _frequencyOffs = 0x2000;
- _algorithm = 7;
-
- _buffer = 0;
- _buflen = 0;
-
- int i;
- for (i = 0; i < ARRAYSIZE(_opr); ++i)
- _opr[i] = new Operator2612 (this);
- velocity(0);
-}
-
-Voice2612::~Voice2612() {
- int i;
- for (i = 0; i < ARRAYSIZE(_opr); ++i)
- delete _opr[i];
- free(_buffer);
-}
-
-void Voice2612::velocity(int velo) {
- _velocity = velo;
-#if 0
- int v = (velo * _control7) >> 7;
-#else
- int v = velo + (_control7 - 127) * 4;
-#endif
- bool iscarrier[8][4] = {
- { false, false, false, true, }, //0
- { false, false, false, true, }, //1
- { false, false, false, true, }, //2
- { false, false, false, true, }, //3
- { false, true, false, true, }, //4
- { false, true, true, true, }, //5
- { false, true, true, true, }, //6
- { true, true, true, true, }, //7
- };
- int opr;
- for (opr = 0; opr < 4; opr++)
- if (iscarrier[_algorithm][opr])
- _opr[opr]->velocity(v);
- else
- _opr[opr]->velocity(127);
-}
-
-void Voice2612::setControlParameter(int control, int value) {
- switch (control) {
- case 7:
- _control7 = value;
- velocity(_velocity);
- break;
- case 123:
- // All notes off
- noteOff(_note);
- };
-}
-
-void Voice2612::setInstrument(byte const *instrument) {
- if (instrument == NULL)
- return;
-
- _algorithm = instrument[32] & 7;
- _opr[0]->feedbackLevel((instrument[32] >> 3) & 7);
- _opr[1]->feedbackLevel(0);
- _opr[2]->feedbackLevel(0);
- _opr[3]->feedbackLevel(0);
- _opr[0]->setInstrument(instrument + 0);
- _opr[1]->setInstrument(instrument + 2);
- _opr[2]->setInstrument(instrument + 1);
- _opr[3]->setInstrument(instrument + 3);
-}
-
-void Voice2612::nextTick(int *outbuf, int buflen) {
- if (_velocity == 0)
- return;
-
- if (_buflen < buflen) {
- free(_buffer);
- _buflen = buflen;
- _buffer = (int *) malloc(sizeof(int) * buflen * 2);
- }
-
- int *buf1 = _buffer;
- int *buf2 = _buffer + buflen;
- memset(_buffer, 0, sizeof(int) * buflen * 2);
-
- switch (_algorithm) {
- case 0:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf2, buf1, buflen);
- memset (buf2, 0, sizeof (int) * buflen);
- _opr[2]->nextTick(buf1, buf2, buflen);
- _opr[3]->nextTick(buf2, outbuf, buflen);
- break;
- case 1:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf1, buf2, buflen);
- _opr[2]->nextTick(buf2, buf1, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- case 2:
- _opr[1]->nextTick(buf1, buf2, buflen);
- _opr[2]->nextTick(buf2, buf1, buflen);
- memset(buf2, 0, sizeof(int) * buflen);
- _opr[0]->nextTick(buf2, buf1, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- case 3:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf2, buf1, buflen);
- memset(buf2, 0, sizeof(int) * buflen);
- _opr[2]->nextTick(buf2, buf1, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- case 4:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf2, outbuf, buflen);
- _opr[2]->nextTick(buf1, buf1, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- case 5:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf2, outbuf, buflen);
- _opr[2]->nextTick(buf2, outbuf, buflen);
- _opr[3]->nextTick(buf2, outbuf, buflen);
- break;
- case 6:
- _opr[0]->nextTick(buf1, buf2, buflen);
- _opr[1]->nextTick(buf2, outbuf, buflen);
- _opr[2]->nextTick(buf1, outbuf, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- case 7:
- _opr[0]->nextTick(buf1, outbuf, buflen);
- _opr[1]->nextTick(buf1, outbuf, buflen);
- _opr[2]->nextTick(buf1, outbuf, buflen);
- _opr[3]->nextTick(buf1, outbuf, buflen);
- break;
- };
-}
-
-void Voice2612::noteOn(int n, int onVelo) {
- _note = n;
- velocity(onVelo);
- recalculateFrequency();
- int i;
- for (i = 0; i < ARRAYSIZE(_opr); i++)
- _opr[i]->keyOn();
-}
-
-bool Voice2612::noteOff(int note) {
- if (_note != note)
- return false;
- int i;
- for (i = 0; i < ARRAYSIZE(_opr); i++)
- _opr[i]->keyOff();
- return true;
-}
-
-void Voice2612::pitchBend(int value) {
- _frequencyOffs = value;
- recalculateFrequency();
-}
-
-void Voice2612::recalculateFrequency() {
- //
- //
- //
- int32 basefreq = frequencyTable[_note];
- int cfreq = frequencyTable[_note - (_note % 12)];
- int oct = _note / 12;
- int fnum = (int) (((double)basefreq * (1 << 13)) / cfreq);
- fnum += _frequencyOffs - 0x2000;
- if (fnum < 0x2000) {
- fnum += 0x2000;
- oct--;
- }
- if (fnum >= 0x4000) {
- fnum -= 0x2000;
- oct++;
- }
-
- //
- _frequency = (int) ((frequencyTable[oct*12] * (double)fnum) / 8);
-
- int i;
- for (i = 0; i < ARRAYSIZE(_opr); i++)
- _opr[i]->frequency(_frequency);
-}
-
-////////////////////////////////////////
-//
-// MidiChannel_YM2612
-//
-////////////////////////////////////////
-
-MidiChannel_YM2612::MidiChannel_YM2612() {
- _voices = 0;
- _next_voice = 0;
-}
-
-MidiChannel_YM2612::~MidiChannel_YM2612() {
- removeAllVoices();
-}
-
-void MidiChannel_YM2612::removeAllVoices() {
- if (!_voices)
- return;
- Voice2612 *last, *voice = _voices;
- for (; voice; voice = last) {
- last = voice->next;
- delete voice;
- }
- _voices = _next_voice = 0;
-}
-
-void MidiChannel_YM2612::noteOn(byte note, byte onVelo) {
- if (!_voices)
- return;
- _next_voice = _next_voice ? _next_voice : _voices;
- _next_voice->noteOn(note, onVelo);
- _next_voice = _next_voice->next;
-}
-
-void MidiChannel_YM2612::noteOff(byte note) {
- if (!_voices)
- return;
- if (_next_voice == _voices)
- _next_voice = 0;
- Voice2612 *voice = _next_voice;
- do {
- if (!voice)
- voice = _voices;
- if (voice->noteOff(note)) {
- _next_voice = voice;
- break;
- }
- voice = voice->next;
- } while (voice != _next_voice);
-}
-
-void MidiChannel_YM2612::controlChange(byte control, byte value) {
- //
- if (control == 121) {
- // Reset controller
- removeAllVoices();
- } else {
- Voice2612 *voice = _voices;
- for (; voice; voice = voice->next)
- voice->setControlParameter(control, value);
- }
-}
-
-void MidiChannel_YM2612::sysEx_customInstrument(uint32 type, const byte *fmInst) {
- if (type != 'EUP ')
- return;
- Voice2612 *voice = new Voice2612;
- voice->next = _voices;
- _voices = voice;
- voice->_rate = _rate;
- voice->setInstrument(fmInst);
-}
-
-void MidiChannel_YM2612::pitchBend(int16 value) {
- //
- Voice2612 *voice = _voices;
- for (; voice; voice = voice->next)
- voice->pitchBend(value);
-}
-
-void MidiChannel_YM2612::nextTick(int *outbuf, int buflen) {
- Voice2612 *voice = _voices;
- for (; voice; voice = voice->next)
- voice->nextTick(outbuf, buflen);
-}
-
-void MidiChannel_YM2612::rate(uint16 r) {
- _rate = r;
- Voice2612 *voice = _voices;
- for (; voice; voice = voice->next)
- voice->_rate = r;
-}
-
-////////////////////////////////////////
-//
-// MidiDriver_YM2612
-//
-////////////////////////////////////////
-
-MidiDriver_YM2612::MidiDriver_YM2612(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer) {
- _next_voice = 0;
-
- createLookupTables();
- _volume = 256;
- int i;
- for (i = 0; i < ARRAYSIZE(_channel); i++)
- _channel[i] = new MidiChannel_YM2612;
- rate(getRate());
-}
-
-MidiDriver_YM2612::~MidiDriver_YM2612() {
- int i;
- for (i = 0; i < ARRAYSIZE(_channel); i++)
- delete _channel[i];
- removeLookupTables();
-}
-
-int MidiDriver_YM2612::open() {
- if (_isOpen)
- return MERR_ALREADY_OPEN;
-
- MidiDriver_Emulated::open();
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
- return 0;
-}
-
-void MidiDriver_YM2612::close() {
- if (!_isOpen)
- return;
- _isOpen = false;
-
- _mixer->stopHandle(_mixerSoundHandle);
-}
-
-void MidiDriver_YM2612::send(uint32 b) {
- send(b & 0xF, b & 0xFFFFFFF0);
-}
-
-void MidiDriver_YM2612::send(byte chan, uint32 b) {
- //byte param3 = (byte) ((b >> 24) & 0xFF);
- byte param2 = (byte) ((b >> 16) & 0xFF);
- byte param1 = (byte) ((b >> 8) & 0xFF);
- byte cmd = (byte) (b & 0xF0);
- if (chan > ARRAYSIZE(_channel))
- return;
-
- switch (cmd) {
- case 0x80:// Note Off
- _channel[chan]->noteOff(param1);
- break;
- case 0x90: // Note On
- _channel[chan]->noteOn(param1, param2);
- break;
- case 0xA0: // Aftertouch
- break; // Not supported.
- case 0xB0: // Control Change
- _channel[chan]->controlChange(param1, param2);
- break;
- case 0xC0: // Program Change
- _channel[chan]->programChange(param1);
- break;
- case 0xD0: // Channel Pressure
- break; // Not supported.
- case 0xE0: // Pitch Bend
- _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000);
- break;
- case 0xF0: // SysEx
- // We should never get here! SysEx information has to be
- // sent via high-level semantic methods.
- warning("MidiDriver_YM2612: Receiving SysEx command on a send() call");
- break;
-
- default:
- warning("MidiDriver_YM2612: Unknown send() command 0x%02X", cmd);
- }
-}
-
-void MidiDriver_YM2612::sysEx(const byte *msg, uint16 length) {
- if (msg[0] != 0x7C || msg[1] >= ARRAYSIZE(_channel))
- return;
- _channel[msg[1]]->sysEx_customInstrument('EUP ', &msg[2]);
-}
-
-void MidiDriver_YM2612::generateSamples(int16 *data, int len) {
- memset(data, 0, 2 * sizeof(int16) * len);
- nextTick(data, len);
-}
-
-void MidiDriver_YM2612::nextTick(int16 *buf1, int buflen) {
- int *buf0 = (int *)buf1;
-
- int i;
- for (i = 0; i < ARRAYSIZE(_channel); i++)
- _channel[i]->nextTick(buf0, buflen);
-
- for (i = 0; i < buflen; ++i)
- buf1[i*2+1] = buf1[i*2] = ((buf0[i] * volume()) >> 10) & 0xffff;
-}
-
-void MidiDriver_YM2612::rate(uint16 r)
-{
- int i;
- for (i = 0; i < ARRAYSIZE(_channel); i++)
- _channel[i]->rate(r);
-}
-
-void MidiDriver_YM2612::createLookupTables() {
- {
- int i;
- sintbl = new int [2048];
- for (i = 0; i < 2048; i++)
- sintbl[i] = (int)(0xffff * sin(i/2048.0 * 2.0 * M_PI));
- }
-
- {
- int i;
- powtbl = new int [1025];
- for (i = 0; i <= 1024; i++)
- powtbl[i] = (int)(0x10000 * pow(2.0, (i - 512) / 512.0));
- }
-
- {
- int i;
- int block;
-
- static int fnum[] = {
- 0x026a, 0x028f, 0x02b6, 0x02df,
- 0x030b, 0x0339, 0x036a, 0x039e,
- 0x03d5, 0x0410, 0x044e, 0x048f,
- };
-
- // (int)(880.0 * 256.0 * pow(2.0, (note-0x51)/12.0))
- //
- frequencyTable = new int [120];
- for (block = -1; block < 9; block++) {
- for (i = 0; i < 12; i++) {
- double freq = fnum[i] * (166400.0 / 3) * pow(2.0, block-21);
- frequencyTable[(block+1)*12+i] = (int)(256.0 * freq);
- }
- }
-
- keycodeTable = new int [120];
- // detune
- for (block = -1; block < 9; block++) {
- for (i = 0; i < 12; i++) {
- // see p.204
- int f8 = (fnum[i] >> 7) & 1;
- int f9 = (fnum[i] >> 8) & 1;
- int f10 = (fnum[i] >> 9) & 1;
- int f11 = (fnum[i] >> 10) & 1;
- int n4 = f11;
- int n3 = (f11&(f10|f9|f8)) | (~f11&f10&f9&f8);
- int note = n4*2 + n3;
- // see p.207
- keycodeTable[(block+1)*12+i] = block*4 + note;
- }
- }
- }
-
- {
- int freq;
- keyscaleTable = new int [8192];
- keyscaleTable[0] = 0;
- for (freq = 1; freq < 8192; freq++) {
- keyscaleTable[freq] = (int)(log((double)freq) / 9.03 * 32.0) - 1;
- // 8368[Hz] (o9c)
- }
- }
-
- {
- int i;
- attackOut = new int [1024];
- for (i = 0; i < 1024; i++)
- attackOut[i] = (int)(((0x7fff+0x03a5)*30.0) / (30.0+i)) - 0x03a5;
- }
-}
-
-void MidiDriver_YM2612::removeLookupTables() {
- delete[] sintbl;
- delete[] powtbl;
- delete[] frequencyTable;
- delete[] keycodeTable;
- delete[] keyscaleTable;
- delete[] attackOut;
- sintbl = powtbl = frequencyTable = keycodeTable = keyscaleTable = attackOut = 0;
-}
-
-
-// Plugin interface
-
-class TownsEmuMusicPlugin : public MusicPluginObject {
-public:
- const char *getName() const {
- return _s("FM Towns Emulator");
- }
-
- const char *getId() const {
- return "towns";
- }
-
- MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
-};
-
-MusicDevices TownsEmuMusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_TOWNS));
- return devices;
-}
-
-Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- *mididriver = new MidiDriver_YM2612(g_system->getMixer());
-
- return Common::kNoError;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(TOWNS)
- //REGISTER_PLUGIN_DYNAMIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin);
-//#endif
diff --git a/audio/softsynth/ym2612.h b/audio/softsynth/ym2612.h
deleted file mode 100644
index de91fc9..0000000
--- a/audio/softsynth/ym2612.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef SOUND_SOFTSYNTH_Y2612_H
-#define SOUND_SOFTSYNTH_Y2612_H
-
-#include "common/scummsys.h"
-
-#include "audio/softsynth/emumidi.h"
-
-////////////////////////////////////////
-//
-// Class declarations
-//
-////////////////////////////////////////
-
-class Voice2612;
-class Operator2612 {
-protected:
- Voice2612 *_owner;
- enum State { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing };
- State _state;
- int32 _currentLevel;
- int _frequency;
- uint32 _phase;
- int _lastOutput;
- int _feedbackLevel;
- int _detune;
- int _multiple;
- int32 _totalLevel;
- int _keyScale;
- int _velocity;
- int _specifiedTotalLevel;
- int _specifiedAttackRate;
- int _specifiedDecayRate;
- int _specifiedSustainLevel;
- int _specifiedSustainRate;
- int _specifiedReleaseRate;
- int _tickCount;
- int _attackTime;
- int32 _decayRate;
- int32 _sustainLevel;
- int32 _sustainRate;
- int32 _releaseRate;
-
-public:
- Operator2612 (Voice2612 *owner);
- ~Operator2612();
- void feedbackLevel(int level);
- void setInstrument(byte const *instrument);
- void velocity(int velo);
- void keyOn();
- void keyOff();
- void frequency(int freq);
- void nextTick(const int *phaseShift, int *outbuf, int buflen);
- bool inUse() { return (_state != _s_ready); }
-};
-
-class Voice2612 {
-public:
- Voice2612 *next;
- uint16 _rate;
-
-protected:
- Operator2612 *_opr[4];
- int _velocity;
- int _control7;
- int _note;
- int _frequencyOffs;
- int _frequency;
- int _algorithm;
-
- int *_buffer;
- int _buflen;
-
-public:
- Voice2612();
- ~Voice2612();
- void setControlParameter(int control, int value);
- void setInstrument(byte const *instrument);
- void velocity(int velo);
- void nextTick(int *outbuf, int buflen);
- void noteOn(int n, int onVelo);
- bool noteOff(int note);
- void pitchBend(int value);
- void recalculateFrequency();
-};
-
-class MidiChannel_YM2612 : public MidiChannel {
-protected:
- uint16 _rate;
- Voice2612 *_voices;
- Voice2612 *_next_voice;
-
-public:
- void removeAllVoices();
- void nextTick(int *outbuf, int buflen);
- void rate(uint16 r);
-
-public:
- MidiChannel_YM2612();
- virtual ~MidiChannel_YM2612();
-
- // MidiChannel interface
- MidiDriver *device() { return 0; }
- byte getNumber() { return 0; }
- void release() { }
- void send(uint32 b) { }
- void noteOff(byte note);
- void noteOn(byte note, byte onVelo);
- void programChange(byte program) { }
- void pitchBend(int16 value);
- void controlChange(byte control, byte value);
- void pitchBendFactor(byte value) { }
- void sysEx_customInstrument(uint32 type, const byte *instr);
-};
-
-class MidiDriver_YM2612 : public MidiDriver_Emulated {
-protected:
- MidiChannel_YM2612 *_channel[16];
-
- int _next_voice;
- int _volume;
-
-protected:
- void nextTick(int16 *buf1, int buflen);
- int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; }
- void rate(uint16 r);
-
- void generateSamples(int16 *buf, int len);
-
-public:
- MidiDriver_YM2612(Audio::Mixer *mixer);
- virtual ~MidiDriver_YM2612();
-
- static void createLookupTables();
- static void removeLookupTables();
-
- int open();
- void close();
- void send(uint32 b);
- void send(byte channel, uint32 b); // Supports higher than channel 15
- uint32 property(int prop, uint32 param) { return 0; }
-
- void setPitchBendRange(byte channel, uint range) { }
- void sysEx(const byte *msg, uint16 length);
-
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
-
-
- // AudioStream API
- bool isStereo() const { return true; }
- int getRate() const { return _mixer->getOutputRate(); }
-};
-
-#endif
-
diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp
index 8927e8d..2301b2a 100644
--- a/engines/scumm/player_towns.cpp
+++ b/engines/scumm/player_towns.cpp
@@ -26,10 +26,8 @@
namespace Scumm {
-Player_Towns::Player_Towns(ScummEngine *vm, bool isVersion2) : _vm(vm), _v2(isVersion2), _numSoundMax(isVersion2 ? 256 : 200) {
+Player_Towns::Player_Towns(ScummEngine *vm, bool isVersion2) : _vm(vm), _v2(isVersion2), _intf(0), _numSoundMax(isVersion2 ? 256 : 200), _unkFlags(0x33) {
memset(_pcmCurrentSound, 0, sizeof(_pcmCurrentSound));
- _unkFlags = 0x33;
- _intf = 0;
}
void Player_Towns::setSfxVolume(int vol) {
@@ -576,15 +574,16 @@ void Player_Towns_v1::playCdaTrack(int sound, const uint8 *data, bool skipTrackV
_cdaCurrentSound = sound;
}
-Player_Towns_v2::Player_Towns_v2(ScummEngine *vm, IMuse *imuse, Audio::Mixer *mixer, bool disposeIMuse) : Player_Towns(vm, true), _imuse(imuse), _imuseDispose(disposeIMuse) {
+Player_Towns_v2::Player_Towns_v2(ScummEngine *vm, IMuse *imuse, Audio::Mixer *mixer, MidiDriver_TOWNS *driver, bool disposeIMuse, bool disposeDriver) : Player_Towns(vm, true), _imuse(imuse), _driver(driver), _imuseDispose(disposeIMuse), _driverDispose(disposeDriver), _sblData(0) {
_soundOverride = new SoundOvrParameters[_numSoundMax];
memset(_soundOverride, 0, _numSoundMax * sizeof(SoundOvrParameters));
- _sblData = 0;
- _intf = new TownsAudioInterface(mixer, 0);
+ if (_driver)
+ _intf = _driver->intf();
}
Player_Towns_v2::~Player_Towns_v2() {
- delete _intf;
+ if (_driverDispose)
+ delete _driver;
if (_imuseDispose)
delete _imuse;
diff --git a/engines/scumm/player_towns.h b/engines/scumm/player_towns.h
index aa4a1bb..900ea59 100644
--- a/engines/scumm/player_towns.h
+++ b/engines/scumm/player_towns.h
@@ -26,6 +26,7 @@
#include "scumm/scumm.h"
#include "scumm/imuse/imuse.h"
#include "audio/softsynth/fmtowns_pc98/towns_euphony.h"
+#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
namespace Scumm {
@@ -141,7 +142,7 @@ private:
class Player_Towns_v2 : public Player_Towns {
public:
- Player_Towns_v2(ScummEngine *vm, IMuse *imuse, Audio::Mixer *mixer, bool disposeIMuse);
+ Player_Towns_v2(ScummEngine *vm, IMuse *imuse, Audio::Mixer *mixer, MidiDriver_TOWNS *driver, bool disposeIMuse, bool disposeDriver);
~Player_Towns_v2();
bool init();
@@ -170,7 +171,10 @@ private:
uint8 *_sblData;
IMuse *_imuse;
+ MidiDriver_TOWNS *_driver;
+
const bool _imuseDispose;
+ const bool _driverDispose;
};
} // End of namespace Scumm
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 6e95846..63d87c3 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1834,7 +1834,7 @@ void ScummEngine::setupMusic(int midi) {
if (nativeMidiDriver != NULL && _native_mt32)
nativeMidiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
bool multi_midi = ConfMan.getBool("multi_midi") && _musicType != MDT_NONE && (midi & MDT_ADLIB);
- if (_musicType == MDT_ADLIB || multi_midi) {
+ if (_musicType == MDT_ADLIB || (multi_midi && _musicType != MDT_TOWNS)) {
adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB));
adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0);
}
@@ -1842,7 +1842,9 @@ void ScummEngine::setupMusic(int midi) {
_imuse = IMuse::create(_system, nativeMidiDriver, adlibMidiDriver);
if (_game.platform == Common::kPlatformFMTowns) {
- _musicEngine = _townsPlayer = new Player_Towns_v2(this, _imuse, _mixer, true);
+ MidiDriver *townsDriver = 0;
+ townsDriver = (_musicType == MDT_TOWNS) ? nativeMidiDriver : MidiDriver::createMidi(MidiDriver::detectDevice(MDT_TOWNS));
+ _musicEngine = _townsPlayer = new Player_Towns_v2(this, _imuse, _mixer, (MidiDriver_TOWNS*)townsDriver, true, (_musicType != MDT_TOWNS));
if (!_townsPlayer->init())
error("Failed to initialize FM-Towns audio driver");
} else {
Commit: f98be17d74c89558871993559e6486e6edea28e0
https://github.com/scummvm/scummvm/commit/f98be17d74c89558871993559e6486e6edea28e0
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:17-07:00
Commit Message:
FM-TOWNS AUDIO: fix compilation
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
base/plugins.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 8bf6d11..c223d44 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -23,6 +23,7 @@
*/
#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
+#include "common/textconsole.h"
class MidiChannel_TOWNS : public MidiChannel {
public:
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
index e4b3723..bbde75e 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
@@ -25,6 +25,7 @@
#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
#include "audio/musicplugin.h"
#include "common/translation.h"
+#include "common/error.h"
class TownsEmuMusicPlugin : public MusicPluginObject {
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 56bb1e6..4a3b201 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -225,6 +225,7 @@ public:
LINK_PLUGIN(AMIGA)
LINK_PLUGIN(APPLEIIGS)
LINK_PLUGIN(TOWNS)
+ LINK_PLUGIN(PC98)
#if defined(USE_TIMIDITY)
LINK_PLUGIN(TIMIDITY)
#endif
Commit: afacbd459fdd25975e5416b7ccefa6fb6b8e29ee
https://github.com/scummvm/scummvm/commit/afacbd459fdd25975e5416b7ccefa6fb6b8e29ee
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:18-07:00
Commit Message:
FM-TOWNS AUDIO: change internal interface layout
Changed paths:
audio/softsynth/fmtowns_pc98/towns_audio.cpp
audio/softsynth/fmtowns_pc98/towns_audio.h
audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
index ee8327f..065532f 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -21,13 +21,16 @@
*/
#include "audio/softsynth/fmtowns_pc98/towns_audio.h"
+#include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
+
#include "common/endian.h"
#include "common/util.h"
+#include "common/textconsole.h"
#include "backends/audiocd/audiocd.h"
class TownsAudio_PcmChannel {
-friend class TownsAudioInterface;
+friend class TownsAudioInterfaceIntern;
public:
TownsAudio_PcmChannel();
~TownsAudio_PcmChannel();
@@ -77,7 +80,7 @@ private:
};
class TownsAudio_WaveTable {
-friend class TownsAudioInterface;
+friend class TownsAudioInterfaceIntern;
public:
TownsAudio_WaveTable();
~TownsAudio_WaveTable();
@@ -98,14 +101,160 @@ private:
int8 *data;
};
-TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns),
+class TownsAudioInterfaceIntern : public TownsPC98_FmSynth {
+public:
+ TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
+ ~TownsAudioInterfaceIntern();
+
+ static TownsAudioInterfaceIntern *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
+ static void releaseRef();
+ bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver);
+
+ bool init();
+
+ int callback(int command, ...);
+ int processCommand(int command, va_list &args);
+
+ void setMusicVolume(int volume);
+ void setSoundEffectVolume(int volume);
+ // Defines the channels used as sound effect channels for the purpose of ScummVM GUI volume control.
+ // The first 6 bits are the 6 fm channels. The next 8 bits are pcm channels.
+ void setSoundEffectChanMask(int mask);
+
+private:
+ void nextTickEx(int32 *buffer, uint32 bufferSize);
+
+ void timerCallbackA();
+ void timerCallbackB();
+
+ typedef int (TownsAudioInterfaceIntern::*TownsAudioIntfCallback)(va_list &);
+ const TownsAudioIntfCallback *_intfOpcodes;
+
+ int intf_reset(va_list &args);
+ int intf_keyOn(va_list &args);
+ int intf_keyOff(va_list &args);
+ int intf_setPanPos(va_list &args);
+ int intf_setInstrument(va_list &args);
+ int intf_loadInstrument(va_list &args);
+ int intf_setPitch(va_list &args);
+ int intf_setLevel(va_list &args);
+ int intf_chanOff(va_list &args);
+ int intf_writeReg(va_list &args);
+ int intf_writeRegBuffer(va_list &args);
+ int intf_readRegBuffer(va_list &args);
+ int intf_setTimerA(va_list &args);
+ int intf_setTimerB(va_list &args);
+ int intf_enableTimerA(va_list &args);
+ int intf_enableTimerB(va_list &args);
+ int intf_loadSamples(va_list &args);
+ int intf_reserveEffectChannels(va_list &args);
+ int intf_loadWaveTable(va_list &args);
+ int intf_unloadWaveTable(va_list &args);
+ int intf_pcmPlayEffect(va_list &args);
+ int intf_pcmChanOff(va_list &args);
+ int intf_pcmEffectPlaying(va_list &args);
+ int intf_fmKeyOn(va_list &args);
+ int intf_fmKeyOff(va_list &args);
+ int intf_fmSetPanPos(va_list &args);
+ int intf_fmSetInstrument(va_list &args);
+ int intf_fmLoadInstrument(va_list &args);
+ int intf_fmSetPitch(va_list &args);
+ int intf_fmSetLevel(va_list &args);
+ int intf_fmReset(va_list &args);
+ int intf_setOutputVolume(va_list &args);
+ int intf_resetOutputVolume(va_list &args);
+ int intf_updateOutputVolume(va_list &args);
+ int intf_cdaToggle(va_list &args);
+ int intf_pcmUpdateEnvelopeGenerator(va_list &args);
+
+ int intf_notImpl(va_list &args);
+
+ void fmReset();
+ int fmKeyOn(int chan, int note, int velo);
+ int fmKeyOff(int chan);
+ int fmChanOff(int chan);
+ int fmSetPanPos(int chan, int mode);
+ int fmSetInstrument(int chan, int instrId);
+ int fmLoadInstrument(int instrId, const uint8 *data);
+ int fmSetPitch(int chan, int pitch);
+ int fmSetLevel(int chan, int lvl);
+
+ void bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value);
+
+ uint8 _fmChanPlaying;
+ uint8 _fmChanNote[6];
+ int16 _fmChanPitch[6];
+
+ uint8 *_fmSaveReg[2];
+ uint8 *_fmInstruments;
+
+ void pcmReset();
+ int pcmKeyOn(int chan, int note, int velo);
+ int pcmKeyOff(int chan);
+ int pcmChanOff(int chan);
+ int pcmSetPanPos(int chan, int mode);
+ int pcmSetInstrument(int chan, int instrId);
+ int pcmLoadInstrument(int instrId, const uint8 *data);
+ int pcmSetPitch(int chan, int pitch);
+ int pcmSetLevel(int chan, int lvl);
+ void pcmUpdateEnvelopeGenerator(int chan);
+
+ TownsAudio_PcmChannel *_pcmChan;
+ uint8 _pcmChanOut;
+ uint8 _pcmChanReserved;
+ uint8 _pcmChanKeyPressed;
+ uint8 _pcmChanEffectPlaying;
+ uint8 _pcmChanKeyPlaying;
+
+ uint8 _pcmChanNote[8];
+ uint8 _pcmChanVelo[8];
+ uint8 _pcmChanLevel[8];
+
+ uint8 _numReservedChannels;
+ uint8 *_pcmInstruments;
+
+ TownsAudio_WaveTable *_waveTables;
+ uint8 _numWaveTables;
+ uint32 _waveTablesTotalDataSize;
+
+ void pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w);
+
+ void updateOutputVolume();
+ uint8 _outputVolumeFlags;
+ uint8 _outputLevel[16];
+ uint8 _outputMuteFlags;
+
+ const float _baserate;
+ uint32 _timerBase;
+ uint32 _tickLength;
+ uint32 _timer;
+
+ uint16 _musicVolume;
+ uint16 _sfxVolume;
+ int _pcmSfxChanMask;
+
+ TownsAudioInterfacePluginDriver *_drv;
+ bool _ready;
+
+ static TownsAudioInterfaceIntern *_refInstance;
+ static int _refCount;
+
+ static const uint8 _chanFlags[];
+ static const uint16 _frequency[];
+ static const uint8 _carrier[];
+ static const uint8 _fmDefaultInstrument[];
+ static const uint16 _pcmPhase1[];
+ static const uint16 _pcmPhase2[];
+};
+
+TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns),
_fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0),
_baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver),
_pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume),
_outputVolumeFlags(0), _outputMuteFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0),
_pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _ready(false) {
-#define INTCB(x) &TownsAudioInterface::intf_##x
+#define INTCB(x) &TownsAudioInterfaceIntern::intf_##x
static const TownsAudioIntfCallback intfCb[] = {
// 0
INTCB(reset),
@@ -222,7 +371,7 @@ TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfac
_tickLength = 2 * _timerBase;
}
-TownsAudioInterface::~TownsAudioInterface() {
+TownsAudioInterfaceIntern::~TownsAudioInterfaceIntern() {
_ready = false;
deinit();
@@ -234,7 +383,47 @@ TownsAudioInterface::~TownsAudioInterface() {
delete[] _pcmChan;
}
-bool TownsAudioInterface::init() {
+TownsAudioInterfaceIntern *TownsAudioInterfaceIntern::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) {
+ _refCount++;
+ if (_refCount == 1 && _refInstance == 0)
+ _refInstance = new TownsAudioInterfaceIntern(mixer, driver);
+ else if (_refCount < 2 || _refInstance == 0)
+ error("TownsAudioInterfaceIntern::addNewRef(): Internal reference management failure");
+ else if (!_refInstance->checkPluginDriver(driver))
+ error("TownsAudioInterfaceIntern::addNewRef(): Plugin driver conflict");
+
+ return _refInstance;
+}
+
+void TownsAudioInterfaceIntern::releaseRef() {
+ if (!_refCount)
+ return;
+
+ _refCount--;
+
+ if (!_refCount) {
+ delete _refInstance;
+ _refInstance = 0;
+ }
+}
+
+bool TownsAudioInterfaceIntern::checkPluginDriver(TownsAudioInterfacePluginDriver *driver) {
+ if (_refCount <= 1)
+ return true;
+
+ Common::StackLock lock(_mutex);
+
+ if (_drv) {
+ if (driver && driver != _drv)
+ return false;
+ } else {
+ _drv = driver;
+ }
+
+ return true;
+}
+
+bool TownsAudioInterfaceIntern::init() {
if (_ready)
return true;
@@ -258,41 +447,46 @@ bool TownsAudioInterface::init() {
return true;
}
-int TownsAudioInterface::callback(int command, ...) {
+int TownsAudioInterfaceIntern::callback(int command, ...) {
if (!_ready)
return 1;
va_list args;
va_start(args, command);
- if (command > 81) {
- va_end(args);
- return 4;
- }
-
- int res = (this->*_intfOpcodes[command])(args);
+ int res = processCommand(command, args);
va_end(args);
return res;
}
-void TownsAudioInterface::setMusicVolume(int volume) {
+int TownsAudioInterfaceIntern::processCommand(int command, va_list &args) {
+ if (!_ready)
+ return 1;
+
+ if (command < 0 || command > 81)
+ return 4;
+
+ return (this->*_intfOpcodes[command])(args);
+}
+
+void TownsAudioInterfaceIntern::setMusicVolume(int volume) {
_musicVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);
setVolumeIntern(_musicVolume, _sfxVolume);
}
-void TownsAudioInterface::setSoundEffectVolume(int volume) {
+void TownsAudioInterfaceIntern::setSoundEffectVolume(int volume) {
_sfxVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);
setVolumeIntern(_musicVolume, _sfxVolume);
}
-void TownsAudioInterface::setSoundEffectChanMask(int mask) {
+void TownsAudioInterfaceIntern::setSoundEffectChanMask(int mask) {
_pcmSfxChanMask = mask >> 6;
mask &= 0x3f;
setVolumeChannelMasks(~mask, mask);
}
-void TownsAudioInterface::nextTickEx(int32 *buffer, uint32 bufferSize) {
+void TownsAudioInterfaceIntern::nextTickEx(int32 *buffer, uint32 bufferSize) {
if (!_ready)
return;
@@ -343,13 +537,13 @@ void TownsAudioInterface::nextTickEx(int32 *buffer, uint32 bufferSize) {
}
}
-void TownsAudioInterface::timerCallbackA() {
+void TownsAudioInterfaceIntern::timerCallbackA() {
Common::StackLock lock(_mutex);
if (_drv && _ready)
_drv->timerCallback(0);
}
-void TownsAudioInterface::timerCallbackB() {
+void TownsAudioInterfaceIntern::timerCallbackB() {
Common::StackLock lock(_mutex);
if (_ready) {
if (_drv)
@@ -358,62 +552,62 @@ void TownsAudioInterface::timerCallbackB() {
}
}
-int TownsAudioInterface::intf_reset(va_list &args) {
+int TownsAudioInterfaceIntern::intf_reset(va_list &args) {
fmReset();
pcmReset();
callback(68);
return 0;
}
-int TownsAudioInterface::intf_keyOn(va_list &args) {
+int TownsAudioInterfaceIntern::intf_keyOn(va_list &args) {
int chan = va_arg(args, int);
int note = va_arg(args, int);
int velo = va_arg(args, int);
return (chan & 0x40) ? pcmKeyOn(chan, note, velo) : fmKeyOn(chan, note, velo);
}
-int TownsAudioInterface::intf_keyOff(va_list &args) {
+int TownsAudioInterfaceIntern::intf_keyOff(va_list &args) {
int chan = va_arg(args, int);
return (chan & 0x40) ? pcmKeyOff(chan) : fmKeyOff(chan);
}
-int TownsAudioInterface::intf_setPanPos(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setPanPos(va_list &args) {
int chan = va_arg(args, int);
int mode = va_arg(args, int);
return (chan & 0x40) ? pcmSetPanPos(chan, mode) : fmSetPanPos(chan, mode);
}
-int TownsAudioInterface::intf_setInstrument(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setInstrument(va_list &args) {
int chan = va_arg(args, int);
int instrId = va_arg(args, int);
return (chan & 0x40) ? pcmSetInstrument(chan, instrId) : fmSetInstrument(chan, instrId);
}
-int TownsAudioInterface::intf_loadInstrument(va_list &args) {
+int TownsAudioInterfaceIntern::intf_loadInstrument(va_list &args) {
int chanType = va_arg(args, int);
int instrId = va_arg(args, int);
uint8 *instrData = va_arg(args, uint8 *);
return (chanType & 0x40) ? pcmLoadInstrument(instrId, instrData) : fmLoadInstrument(instrId, instrData);
}
-int TownsAudioInterface::intf_setPitch(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setPitch(va_list &args) {
int chan = va_arg(args, int);
int16 pitch = (int16)(va_arg(args, int) & 0xffff);
return (chan & 0x40) ? pcmSetPitch(chan, pitch) : fmSetPitch(chan, pitch);
}
-int TownsAudioInterface::intf_setLevel(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setLevel(va_list &args) {
int chan = va_arg(args, int);
int lvl = va_arg(args, int);
return (chan & 0x40) ? pcmSetLevel(chan, lvl) : fmSetLevel(chan, lvl);
}
-int TownsAudioInterface::intf_chanOff(va_list &args) {
+int TownsAudioInterfaceIntern::intf_chanOff(va_list &args) {
int chan = va_arg(args, int);
return (chan & 0x40) ? pcmChanOff(chan) : fmChanOff(chan);
}
-int TownsAudioInterface::intf_writeReg(va_list &args) {
+int TownsAudioInterfaceIntern::intf_writeReg(va_list &args) {
int part = va_arg(args, int) ? 1 : 0;
int reg = va_arg(args, int);
int val = va_arg(args, int);
@@ -424,7 +618,7 @@ int TownsAudioInterface::intf_writeReg(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_writeRegBuffer(va_list &args) {
+int TownsAudioInterfaceIntern::intf_writeRegBuffer(va_list &args) {
int part = va_arg(args, int) ? 1 : 0;
int reg = va_arg(args, int);
int val = va_arg(args, int);
@@ -436,7 +630,7 @@ int TownsAudioInterface::intf_writeRegBuffer(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_readRegBuffer(va_list &args) {
+int TownsAudioInterfaceIntern::intf_readRegBuffer(va_list &args) {
int part = va_arg(args, int) ? 1 : 0;
int reg = va_arg(args, int);
uint8 *dst = va_arg(args, uint8 *);
@@ -449,7 +643,7 @@ int TownsAudioInterface::intf_readRegBuffer(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_setTimerA(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setTimerA(va_list &args) {
int enable = va_arg(args, int);
int tempo = va_arg(args, int);
@@ -464,7 +658,7 @@ int TownsAudioInterface::intf_setTimerA(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_setTimerB(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setTimerB(va_list &args) {
int enable = va_arg(args, int);
int tempo = va_arg(args, int);
@@ -478,17 +672,17 @@ int TownsAudioInterface::intf_setTimerB(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_enableTimerA(va_list &args) {
+int TownsAudioInterfaceIntern::intf_enableTimerA(va_list &args) {
bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x15);
return 0;
}
-int TownsAudioInterface::intf_enableTimerB(va_list &args) {
+int TownsAudioInterfaceIntern::intf_enableTimerB(va_list &args) {
bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x2a);
return 0;
}
-int TownsAudioInterface::intf_loadSamples(va_list &args) {
+int TownsAudioInterfaceIntern::intf_loadSamples(va_list &args) {
uint32 dest = va_arg(args, uint32);
int size = va_arg(args, int);
uint8 *src = va_arg(args, uint8*);
@@ -511,7 +705,7 @@ int TownsAudioInterface::intf_loadSamples(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_reserveEffectChannels(va_list &args) {
+int TownsAudioInterfaceIntern::intf_reserveEffectChannels(va_list &args) {
int numChan = va_arg(args, int);
if (numChan > 8)
return 3;
@@ -543,7 +737,7 @@ int TownsAudioInterface::intf_reserveEffectChannels(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_loadWaveTable(va_list &args) {
+int TownsAudioInterfaceIntern::intf_loadWaveTable(va_list &args) {
uint8 *data = va_arg(args, uint8 *);
if (_numWaveTables > 127)
return 3;
@@ -570,7 +764,7 @@ int TownsAudioInterface::intf_loadWaveTable(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_unloadWaveTable(va_list &args) {
+int TownsAudioInterfaceIntern::intf_unloadWaveTable(va_list &args) {
int id = va_arg(args, int);
if (id == -1) {
@@ -597,7 +791,7 @@ int TownsAudioInterface::intf_unloadWaveTable(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_pcmPlayEffect(va_list &args) {
+int TownsAudioInterfaceIntern::intf_pcmPlayEffect(va_list &args) {
int chan = va_arg(args, int);
int note = va_arg(args, int);
int velo = va_arg(args, int);
@@ -647,13 +841,13 @@ int TownsAudioInterface::intf_pcmPlayEffect(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_pcmChanOff(va_list &args) {
+int TownsAudioInterfaceIntern::intf_pcmChanOff(va_list &args) {
int chan = va_arg(args, int);
pcmChanOff(chan);
return 0;
}
-int TownsAudioInterface::intf_pcmEffectPlaying(va_list &args) {
+int TownsAudioInterfaceIntern::intf_pcmEffectPlaying(va_list &args) {
int chan = va_arg(args, int);
if (chan < 0x40 || chan > 0x47)
return 1;
@@ -661,54 +855,54 @@ int TownsAudioInterface::intf_pcmEffectPlaying(va_list &args) {
return (_pcmChanEffectPlaying & _chanFlags[chan]) ? 1 : 0;
}
-int TownsAudioInterface::intf_fmKeyOn(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmKeyOn(va_list &args) {
int chan = va_arg(args, int);
int note = va_arg(args, int);
int velo = va_arg(args, int);
return fmKeyOn(chan, note, velo);
}
-int TownsAudioInterface::intf_fmKeyOff(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmKeyOff(va_list &args) {
int chan = va_arg(args, int);
return fmKeyOff(chan);
}
-int TownsAudioInterface::intf_fmSetPanPos(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmSetPanPos(va_list &args) {
int chan = va_arg(args, int);
int mode = va_arg(args, int);
return fmSetPanPos(chan, mode);
}
-int TownsAudioInterface::intf_fmSetInstrument(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmSetInstrument(va_list &args) {
int chan = va_arg(args, int);
int instrId = va_arg(args, int);
return fmSetInstrument(chan, instrId);
}
-int TownsAudioInterface::intf_fmLoadInstrument(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmLoadInstrument(va_list &args) {
int instrId = va_arg(args, int);
uint8 *instrData = va_arg(args, uint8 *);
return fmLoadInstrument(instrId, instrData);
}
-int TownsAudioInterface::intf_fmSetPitch(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmSetPitch(va_list &args) {
int chan = va_arg(args, int);
uint16 freq = va_arg(args, int) & 0xffff;
return fmSetPitch(chan, freq);
}
-int TownsAudioInterface::intf_fmSetLevel(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmSetLevel(va_list &args) {
int chan = va_arg(args, int);
int lvl = va_arg(args, int);
return fmSetLevel(chan, lvl);
}
-int TownsAudioInterface::intf_fmReset(va_list &args) {
+int TownsAudioInterfaceIntern::intf_fmReset(va_list &args) {
fmReset();
return 0;
}
-int TownsAudioInterface::intf_setOutputVolume(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) {
int chanType = va_arg(args, int);
int left = va_arg(args, int);
int right = va_arg(args, int);
@@ -743,7 +937,7 @@ int TownsAudioInterface::intf_setOutputVolume(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_resetOutputVolume(va_list &args) {
+int TownsAudioInterfaceIntern::intf_resetOutputVolume(va_list &args) {
memset(_outputLevel, 0, sizeof(_outputLevel));
_outputMuteFlags = 0;
_outputVolumeFlags = 0;
@@ -751,30 +945,30 @@ int TownsAudioInterface::intf_resetOutputVolume(va_list &args) {
return 0;
}
-int TownsAudioInterface::intf_updateOutputVolume(va_list &args) {
+int TownsAudioInterfaceIntern::intf_updateOutputVolume(va_list &args) {
int flags = va_arg(args, int);
_outputMuteFlags = flags & 3;
updateOutputVolume();
return 0;
}
-int TownsAudioInterface::intf_cdaToggle(va_list &args) {
+int TownsAudioInterfaceIntern::intf_cdaToggle(va_list &args) {
//int mode = va_arg(args, int);
//_unkMask = mode ? 0x7f : 0x3f;
return 0;
}
-int TownsAudioInterface::intf_pcmUpdateEnvelopeGenerator(va_list &args) {
+int TownsAudioInterfaceIntern::intf_pcmUpdateEnvelopeGenerator(va_list &args) {
for (int i = 0; i < 8; i++)
pcmUpdateEnvelopeGenerator(i);
return 0;
}
-int TownsAudioInterface::intf_notImpl(va_list &args) {
+int TownsAudioInterfaceIntern::intf_notImpl(va_list &args) {
return 4;
}
-void TownsAudioInterface::fmReset() {
+void TownsAudioInterfaceIntern::fmReset() {
TownsPC98_FmSynth::reset();
_fmChanPlaying = 0;
@@ -802,7 +996,7 @@ void TownsAudioInterface::fmReset() {
}
}
-int TownsAudioInterface::fmKeyOn(int chan, int note, int velo) {
+int TownsAudioInterfaceIntern::fmKeyOn(int chan, int note, int velo) {
if (chan > 5)
return 1;
if (note < 12 || note > 107 || (velo & 0x80))
@@ -882,7 +1076,7 @@ int TownsAudioInterface::fmKeyOn(int chan, int note, int velo) {
return 0;
}
-int TownsAudioInterface::fmKeyOff(int chan) {
+int TownsAudioInterfaceIntern::fmKeyOff(int chan) {
if (chan > 5)
return 1;
_fmChanPlaying &= ~_chanFlags[chan];
@@ -892,7 +1086,7 @@ int TownsAudioInterface::fmKeyOff(int chan) {
return 0;
}
-int TownsAudioInterface::fmChanOff(int chan) {
+int TownsAudioInterfaceIntern::fmChanOff(int chan) {
if (chan > 5)
return 1;
_fmChanPlaying &= ~_chanFlags[chan];
@@ -910,7 +1104,7 @@ int TownsAudioInterface::fmChanOff(int chan) {
return 0;
}
-int TownsAudioInterface::fmSetPanPos(int chan, int value) {
+int TownsAudioInterfaceIntern::fmSetPanPos(int chan, int value) {
if (chan > 5)
return 1;
@@ -929,7 +1123,7 @@ int TownsAudioInterface::fmSetPanPos(int chan, int value) {
return 0;
}
-int TownsAudioInterface::fmSetInstrument(int chan, int instrId) {
+int TownsAudioInterfaceIntern::fmSetInstrument(int chan, int instrId) {
if (chan > 5)
return 1;
if (instrId > 127)
@@ -973,7 +1167,7 @@ int TownsAudioInterface::fmSetInstrument(int chan, int instrId) {
return 0;
}
-int TownsAudioInterface::fmLoadInstrument(int instrId, const uint8 *data) {
+int TownsAudioInterfaceIntern::fmLoadInstrument(int instrId, const uint8 *data) {
if (instrId > 127)
return 3;
assert(data);
@@ -981,7 +1175,7 @@ int TownsAudioInterface::fmLoadInstrument(int instrId, const uint8 *data) {
return 0;
}
-int TownsAudioInterface::fmSetPitch(int chan, int pitch) {
+int TownsAudioInterfaceIntern::fmSetPitch(int chan, int pitch) {
if (chan > 5)
return 1;
@@ -1068,7 +1262,7 @@ int TownsAudioInterface::fmSetPitch(int chan, int pitch) {
return 0;
}
-int TownsAudioInterface::fmSetLevel(int chan, int lvl) {
+int TownsAudioInterfaceIntern::fmSetLevel(int chan, int lvl) {
if (chan > 5)
return 1;
if (lvl > 127)
@@ -1091,12 +1285,12 @@ int TownsAudioInterface::fmSetLevel(int chan, int lvl) {
return 0;
}
-void TownsAudioInterface::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) {
+void TownsAudioInterfaceIntern::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) {
_fmSaveReg[part][regAddress] = value;
writeReg(part, regAddress, value);
}
-void TownsAudioInterface::pcmReset() {
+void TownsAudioInterfaceIntern::pcmReset() {
_pcmChanOut = 0;
_pcmChanReserved = _pcmChanKeyPressed = _pcmChanEffectPlaying = _pcmChanKeyPlaying = 0;
_numReservedChannels = 0;
@@ -1124,7 +1318,7 @@ void TownsAudioInterface::pcmReset() {
}
}
-int TownsAudioInterface::pcmKeyOn(int chan, int note, int velo) {
+int TownsAudioInterfaceIntern::pcmKeyOn(int chan, int note, int velo) {
if (chan < 0x40 || chan > 0x47)
return 1;
@@ -1195,7 +1389,7 @@ int TownsAudioInterface::pcmKeyOn(int chan, int note, int velo) {
return 0;
}
-int TownsAudioInterface::pcmKeyOff(int chan) {
+int TownsAudioInterfaceIntern::pcmKeyOff(int chan) {
if (chan < 0x40 || chan > 0x47)
return 1;
@@ -1205,7 +1399,7 @@ int TownsAudioInterface::pcmKeyOff(int chan) {
return 0;
}
-int TownsAudioInterface::pcmChanOff(int chan) {
+int TownsAudioInterfaceIntern::pcmChanOff(int chan) {
if (chan < 0x40 || chan > 0x47)
return 1;
@@ -1219,7 +1413,7 @@ int TownsAudioInterface::pcmChanOff(int chan) {
return 0;
}
-int TownsAudioInterface::pcmSetPanPos(int chan, int mode) {
+int TownsAudioInterfaceIntern::pcmSetPanPos(int chan, int mode) {
if (chan > 0x47)
return 1;
if (mode & 0x80)
@@ -1242,7 +1436,7 @@ int TownsAudioInterface::pcmSetPanPos(int chan, int mode) {
return 0;
}
-int TownsAudioInterface::pcmSetInstrument(int chan, int instrId) {
+int TownsAudioInterfaceIntern::pcmSetInstrument(int chan, int instrId) {
if (chan > 0x47)
return 1;
if (instrId > 31)
@@ -1252,7 +1446,7 @@ int TownsAudioInterface::pcmSetInstrument(int chan, int instrId) {
return 0;
}
-int TownsAudioInterface::pcmLoadInstrument(int instrId, const uint8 *data) {
+int TownsAudioInterfaceIntern::pcmLoadInstrument(int instrId, const uint8 *data) {
if (instrId > 31)
return 3;
assert(data);
@@ -1260,7 +1454,7 @@ int TownsAudioInterface::pcmLoadInstrument(int instrId, const uint8 *data) {
return 0;
}
-int TownsAudioInterface::pcmSetPitch(int chan, int pitch) {
+int TownsAudioInterfaceIntern::pcmSetPitch(int chan, int pitch) {
if (chan > 0x47)
return 1;
@@ -1290,7 +1484,7 @@ int TownsAudioInterface::pcmSetPitch(int chan, int pitch) {
return 0;
}
-int TownsAudioInterface::pcmSetLevel(int chan, int lvl) {
+int TownsAudioInterfaceIntern::pcmSetLevel(int chan, int lvl) {
if (chan > 0x47)
return 1;
@@ -1319,7 +1513,7 @@ int TownsAudioInterface::pcmSetLevel(int chan, int lvl) {
return 0;
}
-void TownsAudioInterface::pcmUpdateEnvelopeGenerator(int chan) {
+void TownsAudioInterfaceIntern::pcmUpdateEnvelopeGenerator(int chan) {
TownsAudio_PcmChannel *p = &_pcmChan[chan];
if (!p->envCurrentLevel) {
_pcmChanKeyPlaying &= ~_chanFlags[chan];
@@ -1361,7 +1555,7 @@ void TownsAudioInterface::pcmUpdateEnvelopeGenerator(int chan) {
p->velo = (p->envCurrentLevel >> 8) << 1;
}
-void TownsAudioInterface::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) {
+void TownsAudioInterfaceIntern::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) {
int8 diff = p->note - w->baseNote;
uint16 r = w->rate + w->rateOffs;
uint16 bl = 0;
@@ -1390,7 +1584,7 @@ void TownsAudioInterface::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_
p->step = (s * p->stepPitch) >> 14;
}
-void TownsAudioInterface::updateOutputVolume() {
+void TownsAudioInterfaceIntern::updateOutputVolume() {
// FM Towns seems to support volumes of 0 - 63 for each channel.
// We recalculate sane values for our 0 to 255 volume range and
// balance values for our -128 to 127 volume range
@@ -1405,30 +1599,34 @@ void TownsAudioInterface::updateOutputVolume() {
g_system->getAudioCDManager()->setBalance(balance);
}
-const uint8 TownsAudioInterface::_chanFlags[] = {
+TownsAudioInterfaceIntern *TownsAudioInterfaceIntern::_refInstance = 0;
+
+int TownsAudioInterfaceIntern::_refCount = 0;
+
+const uint8 TownsAudioInterfaceIntern::_chanFlags[] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
};
-const uint16 TownsAudioInterface::_frequency[] = {
+const uint16 TownsAudioInterfaceIntern::_frequency[] = {
0x028C, 0x02B4, 0x02DC, 0x030A, 0x0338, 0x0368, 0x039C, 0x03D4, 0x040E, 0x044A, 0x048C, 0x04D0
};
-const uint8 TownsAudioInterface::_carrier[] = {
+const uint8 TownsAudioInterfaceIntern::_carrier[] = {
0x10, 0x10, 0x10, 0x10, 0x30, 0x70, 0x70, 0xF0
};
-const uint8 TownsAudioInterface::_fmDefaultInstrument[] = {
+const uint8 TownsAudioInterfaceIntern::_fmDefaultInstrument[] = {
0x45, 0x4C, 0x45, 0x50, 0x49, 0x41, 0x4E, 0x4F, 0x01, 0x0A, 0x02, 0x01,
0x1E, 0x32, 0x05, 0x00, 0x9C, 0xDC, 0x9C, 0xDC, 0x07, 0x03, 0x14, 0x08,
0x00, 0x03, 0x05, 0x05, 0x55, 0x45, 0x27, 0xA7, 0x04, 0xC0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-const uint16 TownsAudioInterface::_pcmPhase1[] = {
+const uint16 TownsAudioInterfaceIntern::_pcmPhase1[] = {
0x879B, 0x0F37, 0x1F58, 0x306E, 0x4288, 0x55B6, 0x6A08, 0x7F8F, 0x965E, 0xAE88, 0xC882, 0xE341
};
-const uint16 TownsAudioInterface::_pcmPhase2[] = {
+const uint16 TownsAudioInterfaceIntern::_pcmPhase2[] = {
0xFEFE, 0xF1A0, 0xE411, 0xD744, 0xCB2F, 0xBFC7, 0xB504, 0xAAE2, 0xA144, 0x9827, 0x8FAC
};
@@ -1579,3 +1777,37 @@ void TownsAudio_WaveTable::clear() {
data = 0;
}
+TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) {
+ _intf = TownsAudioInterfaceIntern::addNewRef(mixer, driver);
+}
+
+TownsAudioInterface::~TownsAudioInterface() {
+ TownsAudioInterfaceIntern::releaseRef();
+ _intf = 0;
+}
+
+bool TownsAudioInterface::init() {
+ return _intf->init();
+}
+
+int TownsAudioInterface::callback(int command, ...) {
+ va_list args;
+ va_start(args, command);
+
+ int res = _intf->processCommand(command, args);
+
+ va_end(args);
+ return res;
+}
+
+void TownsAudioInterface::setMusicVolume(int volume) {
+ _intf->setMusicVolume(volume);
+}
+
+void TownsAudioInterface::setSoundEffectVolume(int volume) {
+ _intf->setSoundEffectVolume(volume);
+}
+
+void TownsAudioInterface::setSoundEffectChanMask(int mask) {
+ _intf->setSoundEffectChanMask(mask);
+}
\ No newline at end of file
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.h b/audio/softsynth/fmtowns_pc98/towns_audio.h
index f3d863b..2c58d46 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.h
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.h
@@ -23,7 +23,9 @@
#ifndef TOWNS_AUDIO_H
#define TOWNS_AUDIO_H
-#include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
+#include "audio/mixer.h"
+
+class TownsAudioInterfaceIntern;
class TownsAudioInterfacePluginDriver {
public:
@@ -31,10 +33,7 @@ public:
virtual void timerCallback(int timerId) = 0;
};
-class TownsAudio_PcmChannel;
-class TownsAudio_WaveTable;
-
-class TownsAudioInterface : public TownsPC98_FmSynth {
+class TownsAudioInterface {
public:
TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
~TownsAudioInterface();
@@ -50,126 +49,7 @@ public:
void setSoundEffectChanMask(int mask);
private:
- void nextTickEx(int32 *buffer, uint32 bufferSize);
-
- void timerCallbackA();
- void timerCallbackB();
-
- typedef int (TownsAudioInterface::*TownsAudioIntfCallback)(va_list &);
- const TownsAudioIntfCallback *_intfOpcodes;
-
- int intf_reset(va_list &args);
- int intf_keyOn(va_list &args);
- int intf_keyOff(va_list &args);
- int intf_setPanPos(va_list &args);
- int intf_setInstrument(va_list &args);
- int intf_loadInstrument(va_list &args);
- int intf_setPitch(va_list &args);
- int intf_setLevel(va_list &args);
- int intf_chanOff(va_list &args);
- int intf_writeReg(va_list &args);
- int intf_writeRegBuffer(va_list &args);
- int intf_readRegBuffer(va_list &args);
- int intf_setTimerA(va_list &args);
- int intf_setTimerB(va_list &args);
- int intf_enableTimerA(va_list &args);
- int intf_enableTimerB(va_list &args);
- int intf_loadSamples(va_list &args);
- int intf_reserveEffectChannels(va_list &args);
- int intf_loadWaveTable(va_list &args);
- int intf_unloadWaveTable(va_list &args);
- int intf_pcmPlayEffect(va_list &args);
- int intf_pcmChanOff(va_list &args);
- int intf_pcmEffectPlaying(va_list &args);
- int intf_fmKeyOn(va_list &args);
- int intf_fmKeyOff(va_list &args);
- int intf_fmSetPanPos(va_list &args);
- int intf_fmSetInstrument(va_list &args);
- int intf_fmLoadInstrument(va_list &args);
- int intf_fmSetPitch(va_list &args);
- int intf_fmSetLevel(va_list &args);
- int intf_fmReset(va_list &args);
- int intf_setOutputVolume(va_list &args);
- int intf_resetOutputVolume(va_list &args);
- int intf_updateOutputVolume(va_list &args);
- int intf_cdaToggle(va_list &args);
- int intf_pcmUpdateEnvelopeGenerator(va_list &args);
-
- int intf_notImpl(va_list &args);
-
- void fmReset();
- int fmKeyOn(int chan, int note, int velo);
- int fmKeyOff(int chan);
- int fmChanOff(int chan);
- int fmSetPanPos(int chan, int mode);
- int fmSetInstrument(int chan, int instrId);
- int fmLoadInstrument(int instrId, const uint8 *data);
- int fmSetPitch(int chan, int pitch);
- int fmSetLevel(int chan, int lvl);
-
- void bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value);
-
- uint8 _fmChanPlaying;
- uint8 _fmChanNote[6];
- int16 _fmChanPitch[6];
-
- uint8 *_fmSaveReg[2];
- uint8 *_fmInstruments;
-
- void pcmReset();
- int pcmKeyOn(int chan, int note, int velo);
- int pcmKeyOff(int chan);
- int pcmChanOff(int chan);
- int pcmSetPanPos(int chan, int mode);
- int pcmSetInstrument(int chan, int instrId);
- int pcmLoadInstrument(int instrId, const uint8 *data);
- int pcmSetPitch(int chan, int pitch);
- int pcmSetLevel(int chan, int lvl);
- void pcmUpdateEnvelopeGenerator(int chan);
-
- TownsAudio_PcmChannel *_pcmChan;
- uint8 _pcmChanOut;
- uint8 _pcmChanReserved;
- uint8 _pcmChanKeyPressed;
- uint8 _pcmChanEffectPlaying;
- uint8 _pcmChanKeyPlaying;
-
- uint8 _pcmChanNote[8];
- uint8 _pcmChanVelo[8];
- uint8 _pcmChanLevel[8];
-
- uint8 _numReservedChannels;
- uint8 *_pcmInstruments;
-
- TownsAudio_WaveTable *_waveTables;
- uint8 _numWaveTables;
- uint32 _waveTablesTotalDataSize;
-
- void pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w);
-
- void updateOutputVolume();
- uint8 _outputVolumeFlags;
- uint8 _outputLevel[16];
- uint8 _outputMuteFlags;
-
- const float _baserate;
- uint32 _timerBase;
- uint32 _tickLength;
- uint32 _timer;
-
- uint16 _musicVolume;
- uint16 _sfxVolume;
- int _pcmSfxChanMask;
-
- TownsAudioInterfacePluginDriver *_drv;
- bool _ready;
-
- static const uint8 _chanFlags[];
- static const uint16 _frequency[];
- static const uint8 _carrier[];
- static const uint8 _fmDefaultInstrument[];
- static const uint16 _pcmPhase1[];
- static const uint16 _pcmPhase2[];
+ TownsAudioInterfaceIntern *_intf;
};
#endif
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
index bbde75e..3b46aca 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
@@ -26,6 +26,7 @@
#include "audio/musicplugin.h"
#include "common/translation.h"
#include "common/error.h"
+#include "common/system.h"
class TownsEmuMusicPlugin : public MusicPluginObject {
Commit: 61c5813ccffd232df939e16bd70e8e6f63dc39ce
https://github.com/scummvm/scummvm/commit/61c5813ccffd232df939e16bd70e8e6f63dc39ce
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:19-07:00
Commit Message:
MONKEY2/INDY4 FM-TOWNS: adapt code to latest audio driver changes
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.h
engines/scumm/player_towns.cpp
engines/scumm/player_towns.h
engines/scumm/scumm.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index 658c5a4..cc390a2 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -25,8 +25,8 @@
#ifndef TOWNS_MIDI_H
#define TOWNS_MIDI_H
-#include "audio/mididrv.h"
#include "audio/softsynth/fmtowns_pc98/towns_audio.h"
+#include "audio/mididrv.h"
class MidiChannel_TOWNS;
class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver {
diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp
index 2301b2a..a100af7 100644
--- a/engines/scumm/player_towns.cpp
+++ b/engines/scumm/player_towns.cpp
@@ -574,16 +574,15 @@ void Player_Towns_v1::playCdaTrack(int sound, const uint8 *data, bool skipTrackV
_cdaCurrentSound = sound;
}
-Player_Towns_v2::Player_Towns_v2(ScummEngine *vm, IMuse *imuse, Audio::Mixer *mixer, MidiDriver_TOWNS *driver, bool disposeIMuse, bool disposeDriver) : Player_Towns(vm, true), _imuse(imuse), _driver(driver), _imuseDispose(disposeIMuse), _driverDispose(disposeDriver), _sblData(0) {
+Player_Towns_v2::Player_Towns_v2(ScummEngine *vm, Audio::Mixer *mixer, IMuse *imuse, bool disposeIMuse) : Player_Towns(vm, true), _imuse(imuse), _imuseDispose(disposeIMuse), _sblData(0) {
_soundOverride = new SoundOvrParameters[_numSoundMax];
memset(_soundOverride, 0, _numSoundMax * sizeof(SoundOvrParameters));
- if (_driver)
- _intf = _driver->intf();
+ _intf = new TownsAudioInterface(mixer, 0);
}
Player_Towns_v2::~Player_Towns_v2() {
- if (_driverDispose)
- delete _driver;
+ delete _intf;
+ _intf = 0;
if (_imuseDispose)
delete _imuse;
diff --git a/engines/scumm/player_towns.h b/engines/scumm/player_towns.h
index 900ea59..470020d 100644
--- a/engines/scumm/player_towns.h
+++ b/engines/scumm/player_towns.h
@@ -142,7 +142,7 @@ private:
class Player_Towns_v2 : public Player_Towns {
public:
- Player_Towns_v2(ScummEngine *vm, IMuse *imuse, Audio::Mixer *mixer, MidiDriver_TOWNS *driver, bool disposeIMuse, bool disposeDriver);
+ Player_Towns_v2(ScummEngine *vm, Audio::Mixer *mixer, IMuse *imuse, bool disposeIMuse);
~Player_Towns_v2();
bool init();
@@ -170,11 +170,9 @@ private:
SoundOvrParameters *_soundOverride;
uint8 *_sblData;
+
IMuse *_imuse;
- MidiDriver_TOWNS *_driver;
-
const bool _imuseDispose;
- const bool _driverDispose;
};
} // End of namespace Scumm
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 63d87c3..b22a532 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1829,24 +1829,26 @@ void ScummEngine::setupMusic(int midi) {
MidiDriver *nativeMidiDriver = 0;
MidiDriver *adlibMidiDriver = 0;
- if (_musicType != MDT_ADLIB)
+ if (_musicType != MDT_ADLIB && _musicType != MDT_TOWNS)
nativeMidiDriver = MidiDriver::createMidi(dev);
if (nativeMidiDriver != NULL && _native_mt32)
nativeMidiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
bool multi_midi = ConfMan.getBool("multi_midi") && _musicType != MDT_NONE && (midi & MDT_ADLIB);
- if (_musicType == MDT_ADLIB || (multi_midi && _musicType != MDT_TOWNS)) {
+ if (_musicType == MDT_ADLIB || multi_midi) {
adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB));
adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0);
}
+ if (_musicType == MDT_TOWNS) {
+ adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_TOWNS));
+ adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0);
+ }
_imuse = IMuse::create(_system, nativeMidiDriver, adlibMidiDriver);
if (_game.platform == Common::kPlatformFMTowns) {
- MidiDriver *townsDriver = 0;
- townsDriver = (_musicType == MDT_TOWNS) ? nativeMidiDriver : MidiDriver::createMidi(MidiDriver::detectDevice(MDT_TOWNS));
- _musicEngine = _townsPlayer = new Player_Towns_v2(this, _imuse, _mixer, (MidiDriver_TOWNS*)townsDriver, true, (_musicType != MDT_TOWNS));
+ _musicEngine = _townsPlayer = new Player_Towns_v2(this, _mixer, _imuse, true);
if (!_townsPlayer->init())
- error("Failed to initialize FM-Towns audio driver");
+ error("ScummEngine::setupMusic(): Failed to initialize FM-Towns audio driver");
} else {
_musicEngine = _imuse;
}
@@ -1858,7 +1860,6 @@ void ScummEngine::setupMusic(int midi) {
_imuse->property(IMuse::PROP_GAME_ID, _game.id);
if (ConfMan.hasKey("tempo"))
_imuse->property(IMuse::PROP_TEMPO_BASE, ConfMan.getInt("tempo"));
- // YM2162 driver can't handle midi->getPercussionChannel(), NULL shouldn't init MT-32/GM/GS
if (midi != MDT_NONE) {
_imuse->property(IMuse::PROP_NATIVE_MT32, _native_mt32);
if (MidiDriver::getMusicType(dev) != MT_MT32) // MT-32 Emulation shouldn't be GM/GS initialized
Commit: ad991a7831e2c636ea81507f51f30db26a6699dc
https://github.com/scummvm/scummvm/commit/ad991a7831e2c636ea81507f51f30db26a6699dc
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:21-07:00
Commit Message:
FM TOWNS AUDIO: implement some midi driver functions
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_midi.h
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index c223d44..737e977 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -25,13 +25,62 @@
#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
#include "common/textconsole.h"
-class MidiChannel_TOWNS : public MidiChannel {
+class TownsMidiOutputChannel {
+friend class TownsMidiInputChannel;
public:
- MidiChannel_TOWNS(MidiDriver_TOWNS *driver);
- ~MidiChannel_TOWNS();
+ TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanId);
+ ~TownsMidiOutputChannel();
+
+ void noteOn(uint8 msb, uint16 lsb);
+ void noteOnAdjust(uint8 msb, uint16 lsb);
+ void setupProgram(const uint8 *data, uint8 vol1, uint8 vol2);
+
+ void connect(TownsMidiInputChannel *chan);
+ void disconnect();
+
+ enum CheckPriorityStatus {
+ kDisconnected = -3,
+ kHighPriority = -2
+ };
+
+ int checkPriority(int pri);
+
+private:
+ void keyOn();
+ void keyOff();
+ void internKeyOnFrq(uint16 frq);
+ void out(uint8 chan, uint8 reg, uint8 val);
+
+ TownsMidiInputChannel *_midi;
+ TownsMidiOutputChannel *_prev;
+ TownsMidiOutputChannel *_next;
+ uint8 _fld_f;
+ uint8 _note;
+ uint8 _tl;
+ uint8 _noteOffMarker;
+ uint8 _fld_12;
+ uint8 _fld_13;
+ uint8 _prg;
+ uint8 _chan;
+
+ uint16 _freq;
+ int16 _freqAdjust;
+
+ MidiDriver_TOWNS *_driver;
+
+ static const uint8 _freqMSB[];
+ static const uint16 _freqLSB[];
+};
+
+class TownsMidiInputChannel : public MidiChannel {
+friend class TownsMidiOutputChannel;
+public:
+ TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex);
+ ~TownsMidiInputChannel();
MidiDriver *device() { return _driver; }
- byte getNumber() { return 0; }
+ byte getNumber() { return _chanIndex; }
+ bool allocate();
void release();
void send(uint32 b);
@@ -43,71 +92,247 @@ public:
void controlChange(byte control, byte value);
void pitchBendFactor(byte value);
void priority(byte value);
-
void sysEx_customInstrument(uint32 type, const byte *instr);
private:
+ TownsMidiOutputChannel *_outChan;
+ //TownsMidiInputChannel *_prev;
+ //TownsMidiInputChannel *_next;
+
+ uint8 *_instrument;
+ uint8 _prg;
+ uint8 _chanIndex;
+ uint8 _effectLevel;
+ uint8 _priority;
+ uint8 _vol;
+ uint8 _volEff;
+ uint8 _pan;
+ uint8 _panEff;
+ uint8 _perc;
+ uint8 _percS;
+ uint8 _fld_22;
+ uint8 _pitchBendFactor;
+
+ bool _allocated;
+
MidiDriver_TOWNS *_driver;
};
-MidiChannel_TOWNS::MidiChannel_TOWNS(MidiDriver_TOWNS *driver) : MidiChannel(), _driver(driver) {
+TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex),
+ _midi(0), _prev(0), _next(0), _fld_f(0), _note(0), _tl(0), _noteOffMarker(0), _fld_12(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) {
+}
+TownsMidiOutputChannel::~TownsMidiOutputChannel() {
}
-MidiChannel_TOWNS::~MidiChannel_TOWNS() {
+void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) {
+ _freq = (msb << 7) + lsb;
+ _freqAdjust = 0;
+ internKeyOnFrq(_freq);
+}
+void TownsMidiOutputChannel::noteOnAdjust(uint8 msb, uint16 lsb) {
+ _freq = (msb << 7) + lsb;
+ internKeyOnFrq(_freq + _freqAdjust);
}
-void MidiChannel_TOWNS::release() {
+void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 vol2) {
+ const uint8 *pos = data;
}
-void MidiChannel_TOWNS::send(uint32 b) {
+void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) {
+ if (!chan)
+ return;
+ _midi = chan;
+ _next = chan->_outChan;
+ _prev = 0;
+ chan->_outChan = this;
+ if (_next)
+ _next->_prev = this;
+}
+void TownsMidiOutputChannel::disconnect() {
+ keyOff();
+ TownsMidiOutputChannel *p = _prev;
+ TownsMidiOutputChannel *n = _next;
+
+ if (n)
+ n->_prev = p;
+ if (p)
+ p->_next = n;
+ else
+ _midi->_outChan = n;
+ _midi = 0;
}
-void MidiChannel_TOWNS::noteOff(byte note) {
+int TownsMidiOutputChannel::checkPriority(int pri) {
+ if (!_midi)
+ return kDisconnected;
+
+ if (!_next && pri >= _midi->_priority)
+ return _midi->_priority;
+ return kHighPriority;
}
-void MidiChannel_TOWNS::noteOn(byte note, byte velocity) {
+void TownsMidiOutputChannel::keyOn() {
+ out(_chan, 0x28, 0xf0/*0x30*/ /*???*/);
+}
+
+void TownsMidiOutputChannel::keyOff() {
+ out(_chan, 0x28, 0);
+}
+void TownsMidiOutputChannel::internKeyOnFrq(uint16 frq) {
+ uint8 t = (frq << 1) >> 8;
+ frq = (_freqMSB[t] << 3) | _freqLSB[t] ;
+ out(_chan, 0xa4, frq >> 8);
+ out(_chan, 0xa0, frq & 0xff);
+ out(_chan, 0x28, 0);
+ out(_chan, 0x28, 0xf0/*0x30*/ /*???*/);
}
-void MidiChannel_TOWNS::programChange(byte program) {
+void TownsMidiOutputChannel::out(uint8 chan, uint8 reg, uint8 val) {
+ static const uint8 chanRegOffs[] = { 0, 1, 2, 0, 1, 2 };
+ static const uint8 keyValOffs[] = { 0, 1, 2, 4, 5, 6 };
+ if (reg == 0x28)
+ val = (val & 0xf0) | keyValOffs[chan];
+ if (reg < 0x30)
+ _driver->_intf->callback(19, 0, reg, val);
+ else
+ _driver->_intf->callback(19, chan / 3, (reg & ~3) | chanRegOffs[chan], val);
}
-void MidiChannel_TOWNS::pitchBend(int16 bend) {
+const uint8 TownsMidiOutputChannel::_freqMSB[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x80, 0x81, 0x83, 0x85,
+ 0x87, 0x88, 0x8A, 0x8C, 0x8E, 0x8F, 0x91, 0x93, 0x95, 0x96, 0x98, 0x9A,
+ 0x9C, 0x9E, 0x9F, 0xA1, 0xA3, 0xA5, 0xA6, 0xA8, 0xAA, 0xAC, 0xAD, 0xAF,
+ 0xB1, 0xB3, 0xB4, 0xB6, 0xB8, 0xBA, 0xBC, 0xBD, 0xBF, 0xC1, 0xC3, 0xC4,
+ 0xC6, 0xC8, 0xCA, 0xCB, 0xCD, 0xCF, 0xD1, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA,
+ 0xDB, 0xDD, 0xDF, 0xE1, 0xE2, 0xE4, 0xE6, 0xE8, 0xE9, 0xEB, 0xED, 0xEF
+};
+const uint16 TownsMidiOutputChannel::_freqLSB[] = {
+ 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6,
+ 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x0301, 0x032F,
+ 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E,
+ 0x055B, 0x02D6, 0x0301, 0x032F, 0x0360, 0x0393, 0x03C9, 0x0403,
+ 0x0440, 0x0481, 0x04C6, 0x050E, 0x055B, 0x02D6, 0x0301, 0x032F,
+ 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E,
+ 0x055B, 0x02D6, 0x0301, 0x032F, 0x0360, 0x0393, 0x03C9, 0x0403,
+ 0x0440, 0x0481, 0x04C6, 0x050E, 0x055B, 0x02D6, 0x0301, 0x032F,
+ 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E,
+ 0x055B, 0x02D6, 0x0301, 0x032F, 0x0360, 0x0393, 0x03C9, 0x0403,
+ 0x0440, 0x0481, 0x04C6, 0x050E, 0x055B, 0x02D6, 0x0301, 0x032F,
+ 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E,
+ 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B,
+ 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B,
+ 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B,
+ 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B
+};
+
+TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _outChan(0), _prg(0), _chanIndex(chanIndex),
+ _effectLevel(0), _priority(0), _vol(0), _volEff(0), _pan(0), _panEff(0), _perc(0), _percS(0), _pitchBendFactor(0), _fld_22(0), _allocated(false) {
+ _instrument = new uint8[30];
+ memset(_instrument, 0, 30);
}
-void MidiChannel_TOWNS::controlChange(byte control, byte value) {
+TownsMidiInputChannel::~TownsMidiInputChannel() {
+ delete _instrument;
+}
+bool TownsMidiInputChannel::allocate() {
+ if (_allocated)
+ return false;
+ _allocated = true;
+ return true;
}
-void MidiChannel_TOWNS::pitchBendFactor(byte value) {
+void TownsMidiInputChannel::release() {
+ _allocated = false;
+}
+void TownsMidiInputChannel::send(uint32 b) {
+ _driver->send(b | _chanIndex);
}
-void MidiChannel_TOWNS::priority(byte value) {
+void TownsMidiInputChannel::noteOff(byte note) {
+ if (!_outChan)
+ return;
+ if (_outChan->_note != note)
+ return;
+
+ if (_fld_22)
+ _outChan->_noteOffMarker = 1;
+ else
+ _outChan->disconnect();
+}
+
+void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
+ TownsMidiOutputChannel *oc = _driver->allocateOutputChannel(_priority);
+
+ if (!oc)
+ return;
+
+ oc->connect(this);
+
+
+ int vol1 = 0;
+ int vol2 = 0;
+ oc->setupProgram(_instrument, vol1, vol2);
+ //oc->noteOn(m, l);
+
}
-void MidiChannel_TOWNS::sysEx_customInstrument(uint32 type, const byte *instr) {
+void TownsMidiInputChannel::programChange(byte program) {
}
+void TownsMidiInputChannel::pitchBend(int16 bend) {
+
+}
+
+void TownsMidiInputChannel::controlChange(byte control, byte value) {
+
+}
+
+void TownsMidiInputChannel::pitchBendFactor(byte value) {
+
+}
+
+void TownsMidiInputChannel::priority(byte value) {
+ _priority = value;
+}
+
+void TownsMidiInputChannel::sysEx_customInstrument(uint32 type, const byte *instr) {
+ memcpy(_instrument, instr, 30);
+}
+
MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timerBpara(0), _open(false) {
_intf = new TownsAudioInterface(mixer, this);
- _channels = new MidiChannel_TOWNS*[16];
- for (int i = 0; i < 16; i++)
- _channels[i] = new MidiChannel_TOWNS(this);
+
+ _channels = new TownsMidiInputChannel*[32];
+ for (int i = 0; i < 32; i++)
+ _channels[i] = new TownsMidiInputChannel(this, i);
+ _out = new TownsMidiOutputChannel*[6];
+ for (int i = 0; i < 6; i++)
+ _out[i] = new TownsMidiOutputChannel(this, i);
_tickCounter = 0;
_curChan = 0;
- //unbuffered write: _intf->callback(17, part, reg, val);
- //buffered write: _intf->callback(19, part, reg, val);
}
MidiDriver_TOWNS::~MidiDriver_TOWNS() {
@@ -115,9 +340,12 @@ MidiDriver_TOWNS::~MidiDriver_TOWNS() {
delete _intf;
setTimerCallback(0, 0);
- for (int i = 0; i < 16; i++)
+ for (int i = 0; i < 32; i++)
delete _channels[i];
delete[] _channels;
+ for (int i = 0; i < 6; i++)
+ delete _out[i];
+ delete[] _out;
}
int MidiDriver_TOWNS::open() {
@@ -154,14 +382,13 @@ void MidiDriver_TOWNS::send(uint32 b) {
if (chan == 9)
part = &_percussion;
else**/
- MidiChannel_TOWNS *c = _channels[b & 0x0F];
+ TownsMidiInputChannel *c = _channels[b & 0x0F];
switch (cmd) {
case 0x80:
- //part->noteOff(param1);
+ c->noteOff(param1);
break;
case 0x90:
- //part->noteOn(param1, param2);
if (param2)
c->noteOn(param1, param2);
else
@@ -179,7 +406,7 @@ void MidiDriver_TOWNS::send(uint32 b) {
c->pitchBend((param1 | (param2 << 7)) - 0x2000);
break;
case 0xF0:
- warning("MidiDriver_ADLIB: Receiving SysEx command on a send() call");
+ warning("MidiDriver_TOWNS: Receiving SysEx command on a send() call");
break;
default:
@@ -193,25 +420,17 @@ void MidiDriver_TOWNS::setTimerCallback(void *timer_param, Common::TimerManager:
}
uint32 MidiDriver_TOWNS::getBaseTempo() {
- return 0;
+ return 4167;
}
MidiChannel *MidiDriver_TOWNS::allocateChannel() {
- MidiChannel *res = 0;
-
- for (int i = 0; i < 6; i++) {
- if (++_curChan == 6)
- _curChan = 0;
-
- //if (_channels[i]-> //// )
- // return _channels[i];
-
+ for (int i = 0; i < 32; ++i) {
+ TownsMidiInputChannel *chan = _channels[i];
+ if (chan->allocate())
+ return chan;
}
- //if (res)
- // res->noteOff();
-
- return res;
+ return 0;
}
MidiChannel *MidiDriver_TOWNS::getPercussionChannel() {
@@ -237,3 +456,26 @@ void MidiDriver_TOWNS::timerCallback(int timerId) {
break;
}
}
+
+TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) {
+ TownsMidiOutputChannel *res = 0;
+
+ for (int i = 0; i < 6; i++) {
+ if (++_curChan == 6)
+ _curChan = 0;
+
+ int s = _out[i]->checkPriority(pri);
+ if (s == TownsMidiOutputChannel::kDisconnected)
+ return _out[i];
+
+ if (s != TownsMidiOutputChannel::kHighPriority) {
+ pri = s;
+ res = _out[i];
+ }
+ }
+
+ if (res)
+ res->disconnect();
+
+ return res;
+}
\ No newline at end of file
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index cc390a2..1151429 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -28,9 +28,12 @@
#include "audio/softsynth/fmtowns_pc98/towns_audio.h"
#include "audio/mididrv.h"
-class MidiChannel_TOWNS;
+class TownsMidiOutputChannel;
+class TownsMidiInputChannel;
+
class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver {
-friend class MidiChannel_TOWNS;
+friend class TownsMidiInputChannel;
+friend class TownsMidiOutputChannel;
public:
MidiDriver_TOWNS(Audio::Mixer *mixer);
~MidiDriver_TOWNS();
@@ -53,7 +56,10 @@ public:
TownsAudioInterface *intf() { return _intf; }
private:
- MidiChannel_TOWNS **_channels;
+ TownsMidiOutputChannel *allocateOutputChannel(int pri);
+
+ TownsMidiInputChannel **_channels;
+ TownsMidiOutputChannel **_out;
Common::TimerManager::TimerProc _timerBproc;
void *_timerBpara;
Commit: 0dce8bab37efc6ba27d51a61c220a8e5b43ed96c
https://github.com/scummvm/scummvm/commit/0dce8bab37efc6ba27d51a61c220a8e5b43ed96c
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:22-07:00
Commit Message:
FM-TOWNS AUDIO: implement some more midi driver code
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_midi.h
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 737e977..e062024 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -34,6 +34,7 @@ public:
void noteOn(uint8 msb, uint16 lsb);
void noteOnAdjust(uint8 msb, uint16 lsb);
void setupProgram(const uint8 *data, uint8 vol1, uint8 vol2);
+ void noteOnSubSubSub_s1(int index, uint8 c, const uint8 *instr);
void connect(TownsMidiInputChannel *chan);
void disconnect();
@@ -49,25 +50,45 @@ private:
void keyOn();
void keyOff();
void internKeyOnFrq(uint16 frq);
- void out(uint8 chan, uint8 reg, uint8 val);
+ void out(uint8 reg, uint8 val);
TownsMidiInputChannel *_midi;
TownsMidiOutputChannel *_prev;
TownsMidiOutputChannel *_next;
- uint8 _fld_f;
+ uint8 _fld_c;
+ uint8 _chan;
uint8 _note;
- uint8 _tl;
+ uint8 _tl2;
+ uint8 _tl1;
uint8 _noteOffMarker;
- uint8 _fld_12;
+ uint32 _duration;
uint8 _fld_13;
- uint8 _prg;
- uint8 _chan;
+ uint8 _prg;
uint16 _freq;
int16 _freqAdjust;
+ struct StateA {
+ uint8 a[50];
+ } *_stateA;
+
+ struct StateB {
+ uint8 b1;
+ uint8 b2;
+ uint8 b3;
+ uint8 b4;
+ uint8 b5;
+ uint8 b6;
+ uint8 b7;
+ uint8 b8;
+ uint8 b9;
+ uint8 b10;
+ uint8 b11;
+ } *_stateB;
+
MidiDriver_TOWNS *_driver;
+ static const uint8 _chanMap[];
static const uint8 _freqMSB[];
static const uint16 _freqLSB[];
};
@@ -105,24 +126,33 @@ private:
uint8 _effectLevel;
uint8 _priority;
uint8 _vol;
- uint8 _volEff;
+ uint8 _tl;
uint8 _pan;
uint8 _panEff;
- uint8 _perc;
+ int8 _transpose;
uint8 _percS;
uint8 _fld_22;
uint8 _pitchBendFactor;
+ uint16 _freqLSB;
bool _allocated;
MidiDriver_TOWNS *_driver;
+
+ static const uint8 TownsMidiInputChannel::_programAdjustLevel[];
};
TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex),
- _midi(0), _prev(0), _next(0), _fld_f(0), _note(0), _tl(0), _noteOffMarker(0), _fld_12(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) {
+ _midi(0), _prev(0), _next(0), _fld_c(0), _tl2(0), _note(0), _tl1(0), _noteOffMarker(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) {
+ _stateA = new StateA[2];
+ memset(_stateA, 0, 2 * sizeof(StateA));
+ _stateB = new StateB[2];
+ memset(_stateB, 0, 2 * sizeof(StateB));
}
TownsMidiOutputChannel::~TownsMidiOutputChannel() {
+ delete[] _stateA;
+ delete[] _stateB;
}
void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) {
@@ -137,8 +167,54 @@ void TownsMidiOutputChannel::noteOnAdjust(uint8 msb, uint16 lsb) {
}
void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 vol2) {
+ static const uint8 mul[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 };
const uint8 *pos = data;
+ uint8 chan = _chanMap[_chan];
+
+ uint8 mulAmsFms1 = _driver->_chanState[chan].mulAmsFms = *pos++;
+ uint8 tl1 = _driver->_chanState[chan].tl = (*pos++ | 0x3f) - vol1;
+ uint8 attDec1 = _driver->_chanState[chan].attDec = !(*pos++);
+ uint8 sus1 = _driver->_chanState[chan].sus = !(*pos++);
+ uint8 unk1 = _driver->_chanState[chan].unk = *pos++;
+ chan += 3;
+
+ out(0x30, mul[mulAmsFms1 & 0x0f]);
+ out(0x40, (tl1 & 0x3f) + 15);
+ out(0x50, ((attDec1 >> 4) << 1) | ((attDec1 >> 4) & 1));
+ out(0x60, ((attDec1 << 1) | (attDec1 & 1)) & 0x1f);
+ out(0x70, (mulAmsFms1 & 0x20) ^ 0x20 ? ((sus1 & 0x0f) << 1) | 1: 0);
+ out(0x80, sus1);
+
+ uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = *pos++;
+ uint8 tl2 = _driver->_chanState[chan].tl = (*pos++ | 0x3f) - vol2;
+ uint8 attDec2 = _driver->_chanState[chan].attDec = !(*pos++);
+ uint8 sus2 = _driver->_chanState[chan].sus = !(*pos++);
+ uint8 unk2 = _driver->_chanState[chan].unk = *pos++;
+
+ uint8 mul2 = mul[mulAmsFms2 & 0x0f];
+ tl2 = (tl2 & 0x3f) + 15;
+ uint8 ar2 = ((attDec2 >> 4) << 1) | ((attDec2 >> 4) & 1);
+ uint8 dec2 = ((attDec2 << 1) | (attDec2 & 1)) & 0x1f;
+ uint8 sus2r = (mulAmsFms2 & 0x20) ^ 0x20 ? ((sus2 & 0x0f) << 1) | 1: 0;
+
+ for (int i = 4; i < 16; i += 4) {
+ out(0x30 + i, mul2);
+ out(0x40 + i, tl2);
+ out(0x50 + i, ar2);
+ out(0x60 + i, dec2);
+ out(0x70 + i, sus2r);
+ out(0x80 + i, sus2);
+ }
+
+ uint8 t = _driver->_chanState[chan /*_chan*/ /*???*/].fgAlg = *pos;
+ out(0xb0, ((t & 0x0e) << 2) | (((t & 1) << 1) + 5));
+ t = mulAmsFms1 | mulAmsFms2;
+ out(0xb4, 0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5));
+}
+void TownsMidiOutputChannel::noteOnSubSubSub_s1(int index, uint8 c, const uint8 *instr) {
+ StateA *a = &_stateA[index];
+ StateB *b = &_stateB[index];
}
void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) {
@@ -177,34 +253,38 @@ int TownsMidiOutputChannel::checkPriority(int pri) {
}
void TownsMidiOutputChannel::keyOn() {
- out(_chan, 0x28, 0xf0/*0x30*/ /*???*/);
+ out(0x28, 0xf0/*0x30*/ /*???*/);
}
void TownsMidiOutputChannel::keyOff() {
- out(_chan, 0x28, 0);
+ out(0x28, 0);
}
void TownsMidiOutputChannel::internKeyOnFrq(uint16 frq) {
uint8 t = (frq << 1) >> 8;
frq = (_freqMSB[t] << 3) | _freqLSB[t] ;
- out(_chan, 0xa4, frq >> 8);
- out(_chan, 0xa0, frq & 0xff);
- out(_chan, 0x28, 0);
- out(_chan, 0x28, 0xf0/*0x30*/ /*???*/);
+ out(0xa4, frq >> 8);
+ out(0xa0, frq & 0xff);
+ out(0x28, 0);
+ out(0x28, 0xf0/*0x30*/ /*???*/);
}
-void TownsMidiOutputChannel::out(uint8 chan, uint8 reg, uint8 val) {
+void TownsMidiOutputChannel::out(uint8 reg, uint8 val) {
static const uint8 chanRegOffs[] = { 0, 1, 2, 0, 1, 2 };
static const uint8 keyValOffs[] = { 0, 1, 2, 4, 5, 6 };
if (reg == 0x28)
- val = (val & 0xf0) | keyValOffs[chan];
+ val = (val & 0xf0) | keyValOffs[_chan];
if (reg < 0x30)
- _driver->_intf->callback(19, 0, reg, val);
+ _driver->_intf->callback(17, 0, reg, val);
else
- _driver->_intf->callback(19, chan / 3, (reg & ~3) | chanRegOffs[chan], val);
+ _driver->_intf->callback(17, _chan / 3, (reg & ~3) | chanRegOffs[_chan], val);
}
+const uint8 TownsMidiOutputChannel::_chanMap[] = {
+ 0, 1, 2, 8, 9, 10
+};
+
const uint8 TownsMidiOutputChannel::_freqMSB[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -244,7 +324,7 @@ const uint16 TownsMidiOutputChannel::_freqLSB[] = {
};
TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _outChan(0), _prg(0), _chanIndex(chanIndex),
- _effectLevel(0), _priority(0), _vol(0), _volEff(0), _pan(0), _panEff(0), _perc(0), _percS(0), _pitchBendFactor(0), _fld_22(0), _allocated(false) {
+ _effectLevel(0), _priority(0), _vol(0), _tl(0), _pan(0), _panEff(0), _transpose(0), _percS(0), _pitchBendFactor(0), _fld_22(0), _freqLSB(0), _allocated(false) {
_instrument = new uint8[30];
memset(_instrument, 0, 30);
}
@@ -289,12 +369,31 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
oc->connect(this);
+ oc->_fld_c = _instrument[10] & 1;
+ oc->_note = note;
+ oc->_noteOffMarker = 0;
+ oc->_duration = _instrument[29] * 72;
- int vol1 = 0;
- int vol2 = 0;
- oc->setupProgram(_instrument, vol1, vol2);
- //oc->noteOn(m, l);
-
+ oc->_tl1 = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
+ if (oc->_tl1 > 63)
+ oc->_tl1 = 63;
+
+ oc->_tl2 = (_instrument[6] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)];
+ if (oc->_tl2 > 63)
+ oc->_tl2 = 63;
+
+ oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_tl1 << 5)]] : oc->_tl1, _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_tl2 << 5)]]);
+ oc->noteOn(note + _transpose, _freqLSB);
+
+ if (_instrument[11] & 0x80)
+ oc->noteOnSubSubSub_s1(0, _instrument[11], &_instrument[12]);
+ else
+ oc->_stateA[0].a[0] = 0;
+
+ if (_instrument[20] & 0x80)
+ oc->noteOnSubSubSub_s1(1, _instrument[20], &_instrument[21]);
+ else
+ oc->_stateA[1].a[0] = 0;
}
void TownsMidiInputChannel::programChange(byte program) {
@@ -321,16 +420,39 @@ void TownsMidiInputChannel::sysEx_customInstrument(uint32 type, const byte *inst
memcpy(_instrument, instr, 30);
}
+const uint8 TownsMidiInputChannel::_programAdjustLevel[] = {
+ 0x00, 0x04, 0x07, 0x0B, 0x0D, 0x10, 0x12, 0x14,
+ 0x16, 0x18, 0x1A, 0x1B, 0x1D, 0x1E, 0x1F, 0x21,
+ 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
+ 0x2A, 0x2B, 0x2C, 0x2C, 0x2D, 0x2E, 0x2F, 0x2F,
+ 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, 0x34, 0x35,
+ 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x39,
+ 0x39, 0x3A, 0x3A, 0x3B, 0x3B, 0x3C, 0x3C, 0x3C,
+ 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F
+};
+
MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timerBpara(0), _open(false) {
_intf = new TownsAudioInterface(mixer, this);
_channels = new TownsMidiInputChannel*[32];
for (int i = 0; i < 32; i++)
_channels[i] = new TownsMidiInputChannel(this, i);
+
_out = new TownsMidiOutputChannel*[6];
for (int i = 0; i < 6; i++)
_out[i] = new TownsMidiOutputChannel(this, i);
+ _chanState = new ChanState[32];
+ memset(_chanState, 0, 32 * sizeof(ChanState));
+
+ _chanOutputLevel = new uint8[2048];
+ for (int i = 0; i < 64; i++) {
+ for (int ii = 0; ii < 32; ii++)
+ _chanOutputLevel[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff;
+ }
+ for (int i = 0; i < 64; i++)
+ _chanOutputLevel[i << 5] = 0;
+
_tickCounter = 0;
_curChan = 0;
}
@@ -343,9 +465,13 @@ MidiDriver_TOWNS::~MidiDriver_TOWNS() {
for (int i = 0; i < 32; i++)
delete _channels[i];
delete[] _channels;
+
for (int i = 0; i < 6; i++)
delete _out[i];
delete[] _out;
+
+ delete[] _chanState;
+ delete[] _chanOutputLevel;
}
int MidiDriver_TOWNS::open() {
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index 1151429..6ff8a99 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -61,6 +61,15 @@ private:
TownsMidiInputChannel **_channels;
TownsMidiOutputChannel **_out;
+ struct ChanState {
+ uint8 mulAmsFms;
+ uint8 tl;
+ uint8 attDec;
+ uint8 sus;
+ uint8 fgAlg;
+ uint8 unk;
+ } *_chanState;
+
Common::TimerManager::TimerProc _timerBproc;
void *_timerBpara;
@@ -70,6 +79,8 @@ private:
uint8 _curChan;
bool _open;
+
+ uint8 *_chanOutputLevel;
};
#endif
Commit: df244dd3c100c6cf7ea20b091339821d5458d732
https://github.com/scummvm/scummvm/commit/df244dd3c100c6cf7ea20b091339821d5458d732
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:24-07:00
Commit Message:
FM TOWNS AUDIO: some more midi driver code
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index e062024..8506f35 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -49,7 +49,7 @@ public:
private:
void keyOn();
void keyOff();
- void internKeyOnFrq(uint16 frq);
+ void internKeySetFreq(uint16 frq);
void out(uint8 reg, uint8 val);
TownsMidiInputChannel *_midi;
@@ -158,24 +158,29 @@ TownsMidiOutputChannel::~TownsMidiOutputChannel() {
void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) {
_freq = (msb << 7) + lsb;
_freqAdjust = 0;
- internKeyOnFrq(_freq);
+ internKeySetFreq(_freq);
}
void TownsMidiOutputChannel::noteOnAdjust(uint8 msb, uint16 lsb) {
_freq = (msb << 7) + lsb;
- internKeyOnFrq(_freq + _freqAdjust);
+ internKeySetFreq(_freq + _freqAdjust);
}
void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 vol2) {
+ // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7),
+ // since it is just a modified AdLib driver. It also uses AdLib programs.
+ // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS
+ // music being so bad compared to AdLib (unsuitable data is just forced into the
+ // wrong audio device).
+
static const uint8 mul[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 };
- const uint8 *pos = data;
uint8 chan = _chanMap[_chan];
-
- uint8 mulAmsFms1 = _driver->_chanState[chan].mulAmsFms = *pos++;
- uint8 tl1 = _driver->_chanState[chan].tl = (*pos++ | 0x3f) - vol1;
- uint8 attDec1 = _driver->_chanState[chan].attDec = !(*pos++);
- uint8 sus1 = _driver->_chanState[chan].sus = !(*pos++);
- uint8 unk1 = _driver->_chanState[chan].unk = *pos++;
+
+ uint8 mulAmsFms1 = _driver->_chanState[chan].mulAmsFms = data[0];
+ uint8 tl1 = _driver->_chanState[chan].tl = (data[1] | 0x3f) - vol1;
+ uint8 attDec1 = _driver->_chanState[chan].attDec = ~data[2];
+ uint8 sus1 = _driver->_chanState[chan].sus = ~data[3];
+ uint8 unk1 = _driver->_chanState[chan].unk = data[4];
chan += 3;
out(0x30, mul[mulAmsFms1 & 0x0f]);
@@ -185,11 +190,11 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v
out(0x70, (mulAmsFms1 & 0x20) ^ 0x20 ? ((sus1 & 0x0f) << 1) | 1: 0);
out(0x80, sus1);
- uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = *pos++;
- uint8 tl2 = _driver->_chanState[chan].tl = (*pos++ | 0x3f) - vol2;
- uint8 attDec2 = _driver->_chanState[chan].attDec = !(*pos++);
- uint8 sus2 = _driver->_chanState[chan].sus = !(*pos++);
- uint8 unk2 = _driver->_chanState[chan].unk = *pos++;
+ uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = data[5];
+ uint8 tl2 = _driver->_chanState[chan].tl = (data[6] | 0x3f) - vol2;
+ uint8 attDec2 = _driver->_chanState[chan].attDec = ~data[7];
+ uint8 sus2 = _driver->_chanState[chan].sus = ~data[8];
+ uint8 unk2 = _driver->_chanState[chan].unk = data[9];
uint8 mul2 = mul[mulAmsFms2 & 0x0f];
tl2 = (tl2 & 0x3f) + 15;
@@ -206,9 +211,11 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v
out(0x80 + i, sus2);
}
- uint8 t = _driver->_chanState[chan /*_chan*/ /*???*/].fgAlg = *pos;
- out(0xb0, ((t & 0x0e) << 2) | (((t & 1) << 1) + 5));
- t = mulAmsFms1 | mulAmsFms2;
+ _driver->_chanState[chan].fgAlg = data[10];
+ uint8 alg = 5 + 2 * (data[10] & 1);
+ uint8 fb = 4 * (data[10] & 0x0e);
+ out(0xb0, fb | alg);
+ uint8 t = mulAmsFms1 | mulAmsFms2;
out(0xb4, 0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5));
}
@@ -253,20 +260,30 @@ int TownsMidiOutputChannel::checkPriority(int pri) {
}
void TownsMidiOutputChannel::keyOn() {
- out(0x28, 0xf0/*0x30*/ /*???*/);
+ // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7),
+ // since it is just a modified AdLib driver. It also uses AdLib programs.
+ // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS
+ // music being so bad compared to AdLib (unsuitable data is just forced into the
+ // wrong audio device).
+ out(0x28, 0x30);
}
void TownsMidiOutputChannel::keyOff() {
out(0x28, 0);
}
-void TownsMidiOutputChannel::internKeyOnFrq(uint16 frq) {
+void TownsMidiOutputChannel::internKeySetFreq(uint16 frq) {
uint8 t = (frq << 1) >> 8;
- frq = (_freqMSB[t] << 3) | _freqLSB[t] ;
+ frq = (_freqMSB[t] << 11) | _freqLSB[t] ;
out(0xa4, frq >> 8);
out(0xa0, frq & 0xff);
out(0x28, 0);
- out(0x28, 0xf0/*0x30*/ /*???*/);
+ // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7),
+ // since it is just a modified AdLib driver. It also uses AdLib programs.
+ // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS
+ // music being so bad compared to AdLib (unsuitable data is just forced into the
+ // wrong audio device).
+ out(0x28, 0x30);
}
void TownsMidiOutputChannel::out(uint8 reg, uint8 val) {
@@ -574,7 +591,7 @@ void MidiDriver_TOWNS::timerCallback(int timerId) {
_tickCounter += 10000;
while (_tickCounter >= 4167) {
_tickCounter -= 4167;
- //_timerBproc(_timerBpara);
+ _timerBproc(_timerBpara);
}
}
break;
Commit: 70b2466cd7cac3cf6dea90815e164e5c1ac05c43
https://github.com/scummvm/scummvm/commit/70b2466cd7cac3cf6dea90815e164e5c1ac05c43
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:25-07:00
Commit Message:
FM-TOWNS AUDIO: implement some midi commands
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 8506f35..653cab5 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -32,9 +32,10 @@ public:
~TownsMidiOutputChannel();
void noteOn(uint8 msb, uint16 lsb);
- void noteOnAdjust(uint8 msb, uint16 lsb);
+ void noteOnPitchBend(uint8 msb, uint16 lsb);
void setupProgram(const uint8 *data, uint8 vol1, uint8 vol2);
void noteOnSubSubSub_s1(int index, uint8 c, const uint8 *instr);
+ void setModWheel(uint8 value);
void connect(TownsMidiInputChannel *chan);
void disconnect();
@@ -60,7 +61,7 @@ private:
uint8 _note;
uint8 _tl2;
uint8 _tl1;
- uint8 _noteOffMarker;
+ uint8 _sustainNoteOff;
uint32 _duration;
uint8 _fld_13;
uint8 _prg;
@@ -69,7 +70,9 @@ private:
int16 _freqAdjust;
struct StateA {
- uint8 a[50];
+ uint8 active;
+ uint8 a[48];
+ uint8 modWheel;
} *_stateA;
struct StateB {
@@ -78,7 +81,7 @@ private:
uint8 b3;
uint8 b4;
uint8 b5;
- uint8 b6;
+ uint8 mwu;
uint8 b7;
uint8 b8;
uint8 b9;
@@ -113,9 +116,15 @@ public:
void controlChange(byte control, byte value);
void pitchBendFactor(byte value);
void priority(byte value);
- void sysEx_customInstrument(uint32 type, const byte *instr);
+ void sysEx_customInstrument(uint32 type, const byte *instr);
private:
+ void controlModulationWheel(byte value);
+ void controlVolume(byte value);
+ void controlPanPos(byte value);
+ void controlSustain(byte value);
+ void controlRelease();
+
TownsMidiOutputChannel *_outChan;
//TownsMidiInputChannel *_prev;
//TownsMidiInputChannel *_next;
@@ -125,14 +134,18 @@ private:
uint8 _chanIndex;
uint8 _effectLevel;
uint8 _priority;
- uint8 _vol;
+ uint8 _ctrlVolume;
uint8 _tl;
uint8 _pan;
uint8 _panEff;
- int8 _transpose;
uint8 _percS;
- uint8 _fld_22;
+ int8 _transpose;
+ uint8 _fld_1f;
+ int8 _detune;
+ uint8 _modWheel;
+ uint8 _sustain;
uint8 _pitchBendFactor;
+ int16 _pitchBend;
uint16 _freqLSB;
bool _allocated;
@@ -143,7 +156,7 @@ private:
};
TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex),
- _midi(0), _prev(0), _next(0), _fld_c(0), _tl2(0), _note(0), _tl1(0), _noteOffMarker(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) {
+ _midi(0), _prev(0), _next(0), _fld_c(0), _tl2(0), _note(0), _tl1(0), _sustainNoteOff(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) {
_stateA = new StateA[2];
memset(_stateA, 0, 2 * sizeof(StateA));
_stateB = new StateB[2];
@@ -161,7 +174,7 @@ void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) {
internKeySetFreq(_freq);
}
-void TownsMidiOutputChannel::noteOnAdjust(uint8 msb, uint16 lsb) {
+void TownsMidiOutputChannel::noteOnPitchBend(uint8 msb, uint16 lsb) {
_freq = (msb << 7) + lsb;
internKeySetFreq(_freq + _freqAdjust);
}
@@ -224,6 +237,14 @@ void TownsMidiOutputChannel::noteOnSubSubSub_s1(int index, uint8 c, const uint8
StateB *b = &_stateB[index];
}
+void TownsMidiOutputChannel::setModWheel(uint8 value) {
+ if (_stateA[0].active && _stateB[0].mwu)
+ _stateA[0].modWheel = value >> 2;
+
+ if (_stateA[1].active && _stateB[1].mwu)
+ _stateA[1].modWheel = value >> 2;
+}
+
void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) {
if (!chan)
return;
@@ -341,7 +362,8 @@ const uint16 TownsMidiOutputChannel::_freqLSB[] = {
};
TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _outChan(0), _prg(0), _chanIndex(chanIndex),
- _effectLevel(0), _priority(0), _vol(0), _tl(0), _pan(0), _panEff(0), _transpose(0), _percS(0), _pitchBendFactor(0), _fld_22(0), _freqLSB(0), _allocated(false) {
+ _effectLevel(0), _priority(0), _ctrlVolume(0), _tl(0), _pan(0), _panEff(0), _transpose(0), _percS(0), _pitchBendFactor(0), _pitchBend(0), _sustain(0), _freqLSB(0),
+ _fld_1f(0), _detune(0), _modWheel(0), _allocated(false) {
_instrument = new uint8[30];
memset(_instrument, 0, 30);
}
@@ -372,8 +394,8 @@ void TownsMidiInputChannel::noteOff(byte note) {
if (_outChan->_note != note)
return;
- if (_fld_22)
- _outChan->_noteOffMarker = 1;
+ if (_sustain)
+ _outChan->_sustainNoteOff = 1;
else
_outChan->disconnect();
}
@@ -388,7 +410,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
oc->_fld_c = _instrument[10] & 1;
oc->_note = note;
- oc->_noteOffMarker = 0;
+ oc->_sustainNoteOff = 0;
oc->_duration = _instrument[29] * 72;
oc->_tl1 = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
@@ -405,28 +427,49 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
if (_instrument[11] & 0x80)
oc->noteOnSubSubSub_s1(0, _instrument[11], &_instrument[12]);
else
- oc->_stateA[0].a[0] = 0;
+ oc->_stateA[0].active = 0;
if (_instrument[20] & 0x80)
oc->noteOnSubSubSub_s1(1, _instrument[20], &_instrument[21]);
else
- oc->_stateA[1].a[0] = 0;
+ oc->_stateA[1].active = 0;
}
void TownsMidiInputChannel::programChange(byte program) {
-
+ // Dysfunctional since this is all done inside the imuse code
}
void TownsMidiInputChannel::pitchBend(int16 bend) {
-
+ _pitchBend = bend;
+ _freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune;
+ for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next)
+ oc->noteOnPitchBend(oc->_note + oc->_midi->_transpose, _freqLSB);
}
void TownsMidiInputChannel::controlChange(byte control, byte value) {
-
+ switch (control) {
+ case 1:
+ controlModulationWheel(value);
+ break;
+ case 7:
+ controlVolume(value);
+ break;
+ case 10:
+ controlPanPos(value);
+ break;
+ case 64:
+ controlSustain(value);
+ break;
+ default:
+ break;
+ }
}
void TownsMidiInputChannel::pitchBendFactor(byte value) {
-
+ _pitchBendFactor = value;
+ _freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune;
+ for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next)
+ oc->noteOnPitchBend(oc->_note + oc->_midi->_transpose, _freqLSB);
}
void TownsMidiInputChannel::priority(byte value) {
@@ -437,6 +480,47 @@ void TownsMidiInputChannel::sysEx_customInstrument(uint32 type, const byte *inst
memcpy(_instrument, instr, 30);
}
+void TownsMidiInputChannel::controlModulationWheel(byte value) {
+ _modWheel = value;
+ for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next)
+ oc->setModWheel(value);
+}
+
+void TownsMidiInputChannel::controlVolume(byte value) {
+ /* This is all done inside the imuse code
+
+ uint16 v1 = _ctrlVolume + 1;
+ uint16 v2 = value;
+ if (_chanIndex != 16) {
+ _ctrlVolume = value;
+ v2 = value;
+ }
+ _tl = (v1 * v2) >> 7;*/
+
+ _tl = value;
+
+ /* nullsub
+ _outChan->setVolume(_tl);
+ */
+}
+
+void TownsMidiInputChannel::controlPanPos(byte value) {
+ // not supported
+}
+
+void TownsMidiInputChannel::controlSustain(byte value) {
+ _sustain = value;
+ if (!value)
+ controlRelease();
+}
+
+void TownsMidiInputChannel::controlRelease() {
+ for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) {
+ if (oc->_sustainNoteOff)
+ oc->disconnect();
+ }
+}
+
const uint8 TownsMidiInputChannel::_programAdjustLevel[] = {
0x00, 0x04, 0x07, 0x0B, 0x0D, 0x10, 0x12, 0x14,
0x16, 0x18, 0x1A, 0x1B, 0x1D, 0x1E, 0x1F, 0x21,
@@ -521,10 +605,6 @@ void MidiDriver_TOWNS::send(uint32 b) {
byte param1 = (b >> 8) & 0xFF;
byte cmd = b & 0xF0;
- /*AdLibPart *part;
- if (chan == 9)
- part = &_percussion;
- else**/
TownsMidiInputChannel *c = _channels[b & 0x0F];
switch (cmd) {
@@ -538,14 +618,12 @@ void MidiDriver_TOWNS::send(uint32 b) {
c->noteOff(param1);
break;
case 0xB0:
- // supported: 1, 7, 0x40
c->controlChange(param1, param2);
break;
case 0xC0:
c->programChange(param1);
break;
case 0xE0:
- //part->pitchBend((param1 | (param2 << 7)) - 0x2000);
c->pitchBend((param1 | (param2 << 7)) - 0x2000);
break;
case 0xF0:
@@ -577,7 +655,7 @@ MidiChannel *MidiDriver_TOWNS::allocateChannel() {
}
MidiChannel *MidiDriver_TOWNS::getPercussionChannel() {
- return 0;
+ return 0;//_channels[16];
}
void MidiDriver_TOWNS::timerCallback(int timerId) {
Commit: 39e2aa17ed41ea684c8b2960d53771dce5c355e9
https://github.com/scummvm/scummvm/commit/39e2aa17ed41ea684c8b2960d53771dce5c355e9
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:26-07:00
Commit Message:
FM-TOWNS AUDIO: more midi driver code (effect processing)
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_midi.h
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 653cab5..5bd9bda 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -25,6 +25,38 @@
#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
#include "common/textconsole.h"
+struct ChanState {
+ uint8 get(uint8 type) {
+ switch (type) {
+ case 0:
+ return unk1;
+ case 1:
+ return mulAmsFms;
+ case 2:
+ return tl;
+ case 3:
+ return attDec;
+ case 4:
+ return sus;
+ case 5:
+ return fgAlg;
+ case 6:
+ return unk2;
+ default:
+ break;
+ }
+ return 0;
+ }
+
+ uint8 unk1;
+ uint8 mulAmsFms;
+ uint8 tl;
+ uint8 attDec;
+ uint8 sus;
+ uint8 fgAlg;
+ uint8 unk2;
+};
+
class TownsMidiOutputChannel {
friend class TownsMidiInputChannel;
public:
@@ -34,7 +66,7 @@ public:
void noteOn(uint8 msb, uint16 lsb);
void noteOnPitchBend(uint8 msb, uint16 lsb);
void setupProgram(const uint8 *data, uint8 vol1, uint8 vol2);
- void noteOnSubSubSub_s1(int index, uint8 c, const uint8 *instr);
+ void setupEffects(int index, uint8 c, const uint8 *effectData);
void setModWheel(uint8 value);
void connect(TownsMidiInputChannel *chan);
@@ -48,6 +80,43 @@ public:
int checkPriority(int pri);
private:
+ struct StateA {
+ uint8 active;
+ uint8 fld_1;
+ uint8 fld_2;
+ uint8 fld_3;
+ uint8 fld_4;
+ uint8 fld_5;
+ uint8 fld_6;
+ uint8 fld_7;
+ uint8 fld_8;
+ uint32 fld_9;
+ uint32 effectState;
+ uint8 fld_11;
+ uint8 fld_12;
+ uint8 fld_13;
+ uint8 fld_14;
+ uint8 fld_15;
+ uint8 fld_16;
+ uint8 fld_17;
+ uint8 fld_18;
+ uint8 fld_19;
+ uint8 fld_1a;
+ uint8 modWheelImpact;
+ uint8 modWheel;
+ } *_stateA;
+
+ struct StateB {
+ uint32 fld_0;
+ uint8 type;
+ uint8 useModWheel;
+ uint8 fld_6;
+ StateA *a;
+ } *_stateB;
+
+ uint32 getEffectState(uint8 type);
+ void processEffect(StateA *a, const uint8 *effectData);
+
void keyOn();
void keyOff();
void internKeySetFreq(uint16 frq);
@@ -59,8 +128,8 @@ private:
uint8 _fld_c;
uint8 _chan;
uint8 _note;
- uint8 _tl2;
- uint8 _tl1;
+ uint8 _carrierTl;
+ uint8 _modulatorTl;
uint8 _sustainNoteOff;
uint32 _duration;
uint8 _fld_13;
@@ -69,29 +138,11 @@ private:
uint16 _freq;
int16 _freqAdjust;
- struct StateA {
- uint8 active;
- uint8 a[48];
- uint8 modWheel;
- } *_stateA;
-
- struct StateB {
- uint8 b1;
- uint8 b2;
- uint8 b3;
- uint8 b4;
- uint8 b5;
- uint8 mwu;
- uint8 b7;
- uint8 b8;
- uint8 b9;
- uint8 b10;
- uint8 b11;
- } *_stateB;
-
MidiDriver_TOWNS *_driver;
static const uint8 _chanMap[];
+ static const uint8 _chanMap2[];
+ static const uint8 _effectDefs[];
static const uint8 _freqMSB[];
static const uint16 _freqLSB[];
};
@@ -123,11 +174,10 @@ private:
void controlVolume(byte value);
void controlPanPos(byte value);
void controlSustain(byte value);
- void controlRelease();
+
+ void releasePedal();
TownsMidiOutputChannel *_outChan;
- //TownsMidiInputChannel *_prev;
- //TownsMidiInputChannel *_next;
uint8 *_instrument;
uint8 _prg;
@@ -156,7 +206,7 @@ private:
};
TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex),
- _midi(0), _prev(0), _next(0), _fld_c(0), _tl2(0), _note(0), _tl1(0), _sustainNoteOff(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) {
+ _midi(0), _prev(0), _next(0), _fld_c(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) {
_stateA = new StateA[2];
memset(_stateA, 0, 2 * sizeof(StateA));
_stateB = new StateB[2];
@@ -193,7 +243,7 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v
uint8 tl1 = _driver->_chanState[chan].tl = (data[1] | 0x3f) - vol1;
uint8 attDec1 = _driver->_chanState[chan].attDec = ~data[2];
uint8 sus1 = _driver->_chanState[chan].sus = ~data[3];
- uint8 unk1 = _driver->_chanState[chan].unk = data[4];
+ uint8 unk1 = _driver->_chanState[chan].unk2 = data[4];
chan += 3;
out(0x30, mul[mulAmsFms1 & 0x0f]);
@@ -207,7 +257,7 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v
uint8 tl2 = _driver->_chanState[chan].tl = (data[6] | 0x3f) - vol2;
uint8 attDec2 = _driver->_chanState[chan].attDec = ~data[7];
uint8 sus2 = _driver->_chanState[chan].sus = ~data[8];
- uint8 unk2 = _driver->_chanState[chan].unk = data[9];
+ uint8 unk2 = _driver->_chanState[chan].unk2 = data[9];
uint8 mul2 = mul[mulAmsFms2 & 0x0f];
tl2 = (tl2 & 0x3f) + 15;
@@ -232,16 +282,50 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v
out(0xb4, 0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5));
}
-void TownsMidiOutputChannel::noteOnSubSubSub_s1(int index, uint8 c, const uint8 *instr) {
+void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effectData) {
+ uint16 maxVal[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F };
+ uint8 para1[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 };
+
StateA *a = &_stateA[index];
StateB *b = &_stateB[index];
+
+ b->fld_0 = 0;
+ b->useModWheel = c & 0x40;
+ a->fld_11 = c & 0x20;
+ b->fld_6 = c & 0x10;
+ b->type = para1[c & 0x0f];
+ a->fld_9 = maxVal[c & 0x0f];
+ a->fld_1a = 0x1f;
+ a->modWheelImpact = b->useModWheel ? _midi->_modWheel >> 2 : 0x1f;
+
+ switch (b->type) {
+ case 0:
+ a->effectState = _carrierTl;
+ break;
+ case 13:
+ a->effectState = _modulatorTl;
+ break;
+ case 30:
+ a->effectState = 0x1f;
+ b->a->modWheelImpact = 0;
+ break;
+ case 31:
+ a->effectState = 0;
+ b->a->fld_1a = 0;
+ break;
+ default:
+ a->effectState = getEffectState(b->type);
+ break;
+ }
+
+ processEffect(a, effectData);
}
void TownsMidiOutputChannel::setModWheel(uint8 value) {
- if (_stateA[0].active && _stateB[0].mwu)
+ if (_stateA[0].active && _stateB[0].type)
_stateA[0].modWheel = value >> 2;
- if (_stateA[1].active && _stateB[1].mwu)
+ if (_stateA[1].active && _stateB[1].type)
_stateA[1].modWheel = value >> 2;
}
@@ -280,6 +364,30 @@ int TownsMidiOutputChannel::checkPriority(int pri) {
return kHighPriority;
}
+uint32 TownsMidiOutputChannel::getEffectState(uint8 type) {
+ uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan);
+
+ if (type == 28)
+ return 15;
+ else if (type == 29)
+ return 383;
+ else if (type > 29)
+ return 0;
+ else if (type > 12)
+ type -= 13;
+
+ uint32 res = 0;
+ uint8 cs = (_driver->_chanState[chan].get(_effectDefs[type * 4] >> 5) & _effectDefs[type * 4 + 2]) >> _effectDefs[type * 4 + 1];
+ if (_effectDefs[type * 4 + 3])
+ res = _effectDefs[type * 4 + 3] - cs;
+
+ return res;
+}
+
+void TownsMidiOutputChannel::processEffect(StateA *a, const uint8 *effectData) {
+
+}
+
void TownsMidiOutputChannel::keyOn() {
// This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7),
// since it is just a modified AdLib driver. It also uses AdLib programs.
@@ -323,6 +431,18 @@ const uint8 TownsMidiOutputChannel::_chanMap[] = {
0, 1, 2, 8, 9, 10
};
+const uint8 TownsMidiOutputChannel::_chanMap2[] = {
+ 3, 4, 5, 11, 12, 13
+};
+
+const uint8 TownsMidiOutputChannel::_effectDefs[] = {
+ 0x40, 0x00, 0x3F, 0x3F, 0xE0, 0x02, 0x00, 0x00, 0x40, 0x06, 0xC0, 0x00,
+ 0x20, 0x00, 0x0F, 0x00, 0x60, 0x04, 0xF0, 0x0F, 0x60, 0x00, 0x0F, 0x0F,
+ 0x80, 0x04, 0xF0, 0x0F, 0x80, 0x00, 0x0F, 0x0F, 0xE0, 0x00, 0x03, 0x00,
+ 0x20, 0x07, 0x80, 0x00, 0x20, 0x06, 0x40, 0x00, 0x20, 0x05, 0x20, 0x00,
+ 0x20, 0x04, 0x10, 0x00, 0xC0, 0x00, 0x01, 0x00, 0xC0, 0x01, 0x0E, 0x00
+};
+
const uint8 TownsMidiOutputChannel::_freqMSB[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -413,24 +533,24 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
oc->_sustainNoteOff = 0;
oc->_duration = _instrument[29] * 72;
- oc->_tl1 = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
- if (oc->_tl1 > 63)
- oc->_tl1 = 63;
+ oc->_modulatorTl = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
+ if (oc->_modulatorTl > 63)
+ oc->_modulatorTl = 63;
- oc->_tl2 = (_instrument[6] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)];
- if (oc->_tl2 > 63)
- oc->_tl2 = 63;
+ oc->_carrierTl = (_instrument[6] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)];
+ if (oc->_carrierTl > 63)
+ oc->_carrierTl = 63;
- oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_tl1 << 5)]] : oc->_tl1, _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_tl2 << 5)]]);
+ oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]);
oc->noteOn(note + _transpose, _freqLSB);
if (_instrument[11] & 0x80)
- oc->noteOnSubSubSub_s1(0, _instrument[11], &_instrument[12]);
+ oc->setupEffects(0, _instrument[11], &_instrument[12]);
else
oc->_stateA[0].active = 0;
if (_instrument[20] & 0x80)
- oc->noteOnSubSubSub_s1(1, _instrument[20], &_instrument[21]);
+ oc->setupEffects(1, _instrument[20], &_instrument[21]);
else
oc->_stateA[1].active = 0;
}
@@ -511,10 +631,10 @@ void TownsMidiInputChannel::controlPanPos(byte value) {
void TownsMidiInputChannel::controlSustain(byte value) {
_sustain = value;
if (!value)
- controlRelease();
+ releasePedal();
}
-void TownsMidiInputChannel::controlRelease() {
+void TownsMidiInputChannel::releasePedal() {
for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) {
if (oc->_sustainNoteOff)
oc->disconnect();
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index 6ff8a99..8cffdd7 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -28,8 +28,10 @@
#include "audio/softsynth/fmtowns_pc98/towns_audio.h"
#include "audio/mididrv.h"
+
class TownsMidiOutputChannel;
class TownsMidiInputChannel;
+struct ChanState;
class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver {
friend class TownsMidiInputChannel;
@@ -61,14 +63,7 @@ private:
TownsMidiInputChannel **_channels;
TownsMidiOutputChannel **_out;
- struct ChanState {
- uint8 mulAmsFms;
- uint8 tl;
- uint8 attDec;
- uint8 sus;
- uint8 fgAlg;
- uint8 unk;
- } *_chanState;
+ ChanState *_chanState;
Common::TimerManager::TimerProc _timerBproc;
void *_timerBpara;
Commit: 0e819b8dfa0c7761b7534272d1836e6f28a54335
https://github.com/scummvm/scummvm/commit/0e819b8dfa0c7761b7534272d1836e6f28a54335
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:28-07:00
Commit Message:
FM-TOWNS AUDIO: some renaming in the euphony driver code
Changed paths:
audio/softsynth/fmtowns_pc98/towns_euphony.cpp
audio/softsynth/fmtowns_pc98/towns_euphony.h
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_midi.h
engines/kyra/sound_towns.cpp
engines/scumm/player_towns.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
index 49c156f..cb6cfc5 100644
--- a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
@@ -27,7 +27,7 @@
TownsEuphonyDriver::TownsEuphonyDriver(Audio::Mixer *mixer) : _activeChannels(0), _sustainChannels(0),
_assignedChannels(0), _paraCount(0), _command(0), _tEnable(0), _tMode(0), _tOrdr(0), _tLevel(0),
- _tTranspose(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0),
+ _tDetune(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0),
_tempoControlMode(0) {
_para[0] = _para[1] = 0;
_intf = new TownsAudioInterface(mixer, this);
@@ -44,7 +44,7 @@ TownsEuphonyDriver::~TownsEuphonyDriver() {
delete[] _tMode;
delete[] _tOrdr;
delete[] _tLevel;
- delete[] _tTranspose;
+ delete[] _tDetune;
}
bool TownsEuphonyDriver::init() {
@@ -59,7 +59,7 @@ bool TownsEuphonyDriver::init() {
delete[] _tMode;
delete[] _tOrdr;
delete[] _tLevel;
- delete[] _tTranspose;
+ delete[] _tDetune;
_activeChannels = new int8[16];
_sustainChannels = new int8[16];
@@ -70,7 +70,7 @@ bool TownsEuphonyDriver::init() {
_tMode = new uint8[32];
_tOrdr = new uint8[32];
_tLevel = new int8[32];
- _tTranspose = new int8[32];
+ _tDetune = new int8[32];
reset();
@@ -220,21 +220,21 @@ void TownsEuphonyDriver::setOutputVolume(int mode, int volLeft, int volRight) {
_intf->callback(67, mode, volLeft, volRight);
}
-int TownsEuphonyDriver::chanEnable(int tableEntry, int val) {
+int TownsEuphonyDriver::configChan_enable(int tableEntry, int val) {
if (tableEntry > 31)
return 3;
_tEnable[tableEntry] = val;
return 0;
}
-int TownsEuphonyDriver::chanMode(int tableEntry, int val) {
+int TownsEuphonyDriver::configChan_setMode(int tableEntry, int val) {
if (tableEntry > 31)
return 3;
_tMode[tableEntry] = val;
return 0;
}
-int TownsEuphonyDriver::chanOrdr(int tableEntry, int val) {
+int TownsEuphonyDriver::configChan_remap(int tableEntry, int val) {
if (tableEntry > 31)
return 3;
if (val < 16)
@@ -242,7 +242,7 @@ int TownsEuphonyDriver::chanOrdr(int tableEntry, int val) {
return 0;
}
-int TownsEuphonyDriver::chanVolumeShift(int tableEntry, int val) {
+int TownsEuphonyDriver::configChan_adjustVolume(int tableEntry, int val) {
if (tableEntry > 31)
return 3;
if (val <= 40)
@@ -250,11 +250,11 @@ int TownsEuphonyDriver::chanVolumeShift(int tableEntry, int val) {
return 0;
}
-int TownsEuphonyDriver::chanNoteShift(int tableEntry, int val) {
+int TownsEuphonyDriver::configChan_setDetune(int tableEntry, int val) {
if (tableEntry > 31)
return 3;
if (val <= 40)
- _tTranspose[tableEntry] = (int8)(val & 0xff);
+ _tDetune[tableEntry] = (int8)(val & 0xff);
return 0;
}
@@ -325,7 +325,7 @@ void TownsEuphonyDriver::resetTables() {
for (int i = 0; i < 32; i++)
_tOrdr[i] = i & 0x0f;
memset(_tLevel, 0, 32);
- memset(_tTranspose, 0, 32);
+ memset(_tDetune, 0, 32);
}
void TownsEuphonyDriver::resetTempo() {
@@ -672,8 +672,8 @@ bool TownsEuphonyDriver::evtSetupNote() {
uint8 velo = _musicPos[5];
sendEvent(mode, evt);
- sendEvent(mode, applyNoteShift(note));
- sendEvent(mode, applyVolumeShift(velo));
+ sendEvent(mode, applyDetune(note));
+ sendEvent(mode, applyVolumeAdjust(velo));
jumpNextLoop();
if (_musicPos[0] == 0xfe || _musicPos[0] == 0xfd)
@@ -712,7 +712,7 @@ bool TownsEuphonyDriver::evtPolyphonicAftertouch() {
uint8 mode = _tMode[_musicPos[1]];
sendEvent(mode, evt);
- sendEvent(mode, applyNoteShift(_musicPos[4]));
+ sendEvent(mode, applyDetune(_musicPos[4]));
sendEvent(mode, _musicPos[5]);
return false;
@@ -780,8 +780,8 @@ bool TownsEuphonyDriver::evtModeOrdrChange() {
return false;
}
-uint8 TownsEuphonyDriver::applyNoteShift(uint8 in) {
- int out = _tTranspose[_musicPos[1]];
+uint8 TownsEuphonyDriver::applyDetune(uint8 in) {
+ int out = _tDetune[_musicPos[1]];
if (!out)
return in;
out += (in & 0x7f);
@@ -795,7 +795,7 @@ uint8 TownsEuphonyDriver::applyNoteShift(uint8 in) {
return out & 0xff;
}
-uint8 TownsEuphonyDriver::applyVolumeShift(uint8 in) {
+uint8 TownsEuphonyDriver::applyVolumeAdjust(uint8 in) {
int out = _tLevel[_musicPos[1]];
out += (in & 0x7f);
out = CLIP(out, 1, 127);
diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.h b/audio/softsynth/fmtowns_pc98/towns_euphony.h
index a8f22f5..ae36d12 100644
--- a/audio/softsynth/fmtowns_pc98/towns_euphony.h
+++ b/audio/softsynth/fmtowns_pc98/towns_euphony.h
@@ -55,11 +55,11 @@ public:
void setOutputVolume(int chanType, int volLeft, int volRight);
- int chanEnable(int tableEntry, int val);
- int chanMode(int tableEntry, int val);
- int chanOrdr(int tableEntry, int val);
- int chanVolumeShift(int tableEntry, int val);
- int chanNoteShift(int tableEntry, int val);
+ int configChan_enable(int tableEntry, int val);
+ int configChan_setMode(int tableEntry, int val);
+ int configChan_remap(int tableEntry, int val);
+ int configChan_adjustVolume(int tableEntry, int val);
+ int configChan_setDetune(int tableEntry, int val);
int assignChannel(int chan, int tableEntry);
@@ -111,8 +111,8 @@ private:
return false;
}
- uint8 applyNoteShift(uint8 in);
- uint8 applyVolumeShift(uint8 in);
+ uint8 applyDetune(uint8 in);
+ uint8 applyVolumeAdjust(uint8 in);
void sendNoteOff();
void sendNoteOn();
@@ -136,7 +136,7 @@ private:
uint8 *_tMode;
uint8 *_tOrdr;
int8 *_tLevel;
- int8 *_tTranspose;
+ int8 *_tDetune;
struct DlEvent {
uint8 evt;
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 5bd9bda..22f7bc0 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -25,38 +25,6 @@
#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
#include "common/textconsole.h"
-struct ChanState {
- uint8 get(uint8 type) {
- switch (type) {
- case 0:
- return unk1;
- case 1:
- return mulAmsFms;
- case 2:
- return tl;
- case 3:
- return attDec;
- case 4:
- return sus;
- case 5:
- return fgAlg;
- case 6:
- return unk2;
- default:
- break;
- }
- return 0;
- }
-
- uint8 unk1;
- uint8 mulAmsFms;
- uint8 tl;
- uint8 attDec;
- uint8 sus;
- uint8 fgAlg;
- uint8 unk2;
-};
-
class TownsMidiOutputChannel {
friend class TownsMidiInputChannel;
public:
@@ -119,7 +87,7 @@ private:
void keyOn();
void keyOff();
- void internKeySetFreq(uint16 frq);
+ void keyOnSetFreq(uint16 frq);
void out(uint8 reg, uint8 val);
TownsMidiInputChannel *_midi;
@@ -205,6 +173,47 @@ private:
static const uint8 TownsMidiInputChannel::_programAdjustLevel[];
};
+class TownsMidiChanState {
+public:
+ TownsMidiChanState();
+ ~TownsMidiChanState() {}
+ uint8 get(uint8 type);
+
+ uint8 unk1;
+ uint8 mulAmsFms;
+ uint8 tl;
+ uint8 attDec;
+ uint8 sus;
+ uint8 fgAlg;
+ uint8 unk2;
+};
+
+TownsMidiChanState::TownsMidiChanState() {
+ unk1 = mulAmsFms = tl = attDec = sus = fgAlg = unk2 = 0;
+}
+
+uint8 TownsMidiChanState::get(uint8 type) {
+ switch (type) {
+ case 0:
+ return unk1;
+ case 1:
+ return mulAmsFms;
+ case 2:
+ return tl;
+ case 3:
+ return attDec;
+ case 4:
+ return sus;
+ case 5:
+ return fgAlg;
+ case 6:
+ return unk2;
+ default:
+ break;
+ }
+ return 0;
+}
+
TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex),
_midi(0), _prev(0), _next(0), _fld_c(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) {
_stateA = new StateA[2];
@@ -221,12 +230,12 @@ TownsMidiOutputChannel::~TownsMidiOutputChannel() {
void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) {
_freq = (msb << 7) + lsb;
_freqAdjust = 0;
- internKeySetFreq(_freq);
+ keyOnSetFreq(_freq);
}
void TownsMidiOutputChannel::noteOnPitchBend(uint8 msb, uint16 lsb) {
_freq = (msb << 7) + lsb;
- internKeySetFreq(_freq + _freqAdjust);
+ keyOnSetFreq(_freq + _freqAdjust);
}
void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 vol2) {
@@ -401,7 +410,7 @@ void TownsMidiOutputChannel::keyOff() {
out(0x28, 0);
}
-void TownsMidiOutputChannel::internKeySetFreq(uint16 frq) {
+void TownsMidiOutputChannel::keyOnSetFreq(uint16 frq) {
uint8 t = (frq << 1) >> 8;
frq = (_freqMSB[t] << 11) | _freqLSB[t] ;
out(0xa4, frq >> 8);
@@ -556,7 +565,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
}
void TownsMidiInputChannel::programChange(byte program) {
- // Dysfunctional since this is all done inside the imuse code
+ // Dysfunctional since this is all done inside the imuse code
}
void TownsMidiInputChannel::pitchBend(int16 bend) {
@@ -663,8 +672,7 @@ MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timer
for (int i = 0; i < 6; i++)
_out[i] = new TownsMidiOutputChannel(this, i);
- _chanState = new ChanState[32];
- memset(_chanState, 0, 32 * sizeof(ChanState));
+ _chanState = new TownsMidiChanState[32];
_chanOutputLevel = new uint8[2048];
for (int i = 0; i < 64; i++) {
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index 8cffdd7..005c77c 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -31,7 +31,7 @@
class TownsMidiOutputChannel;
class TownsMidiInputChannel;
-struct ChanState;
+class TownsMidiChanState;
class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver {
friend class TownsMidiInputChannel;
@@ -61,9 +61,8 @@ private:
TownsMidiOutputChannel *allocateOutputChannel(int pri);
TownsMidiInputChannel **_channels;
- TownsMidiOutputChannel **_out;
-
- ChanState *_chanState;
+ TownsMidiOutputChannel **_out;
+ TownsMidiChanState *_chanState;
Common::TimerManager::TimerProc _timerBproc;
void *_timerBpara;
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index acf069d..5f4e5a5 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -113,7 +113,7 @@ void SoundTowns::haltTrack() {
for (int i = 0x40; i < 0x46; i++)
_driver->chanVolume(i, 0);
for (int i = 0; i < 32; i++)
- _driver->chanEnable(i, 0);
+ _driver->configChan_enable(i, 0);
_driver->stopParser();
}
@@ -330,15 +330,15 @@ void SoundTowns::playEuphonyTrack(uint32 offset, int loop) {
const uint8 *src = _musicTrackData + 852;
for (int i = 0; i < 32; i++)
- _driver->chanEnable(i, *src++);
+ _driver->configChan_enable(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->chanMode(i, *src++);
+ _driver->configChan_setMode(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->chanOrdr(i, *src++);
+ _driver->configChan_remap(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->chanVolumeShift(i, *src++);
+ _driver->configChan_adjustVolume(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->chanNoteShift(i, *src++);
+ _driver->configChan_setDetune(i, *src++);
src = _musicTrackData + 1748;
for (int i = 0; i < 6; i++)
diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp
index a100af7..f3b790a 100644
--- a/engines/scumm/player_towns.cpp
+++ b/engines/scumm/player_towns.cpp
@@ -500,15 +500,15 @@ void Player_Towns_v1::playEuphonyTrack(int sound, const uint8 *data) {
const uint8 *trackData = src + 150;
for (int i = 0; i < 32; i++)
- _driver->chanEnable(i, *src++);
+ _driver->configChan_enable(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->chanMode(i, 0xff);
+ _driver->configChan_setMode(i, 0xff);
for (int i = 0; i < 32; i++)
- _driver->chanOrdr(i, *src++);
+ _driver->configChan_remap(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->chanVolumeShift(i, *src++);
+ _driver->configChan_adjustVolume(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->chanNoteShift(i, *src++);
+ _driver->configChan_setDetune(i, *src++);
src += 8;
for (int i = 0; i < 6; i++)
Commit: ed13e551d15cc95b20af4837780e2f0995a337e3
https://github.com/scummvm/scummvm/commit/ed13e551d15cc95b20af4837780e2f0995a337e3
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:29-07:00
Commit Message:
FM-TOWNS AUDIO: more midi driver code
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_midi.h
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 22f7bc0..ab1fdbc 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -49,28 +49,25 @@ public:
private:
struct StateA {
- uint8 active;
- uint8 fld_1;
- uint8 fld_2;
- uint8 fld_3;
- uint8 fld_4;
- uint8 fld_5;
- uint8 fld_6;
- uint8 fld_7;
- uint8 fld_8;
- uint32 fld_9;
- uint32 effectState;
+ uint8 numLoop;
+ int32 fld_1;
+ uint32 fld_5;
+ int32 fld_9;
+ int32 effectState;
uint8 fld_11;
- uint8 fld_12;
- uint8 fld_13;
- uint8 fld_14;
- uint8 fld_15;
- uint8 fld_16;
- uint8 fld_17;
- uint8 fld_18;
- uint8 fld_19;
+ uint8 ar1[4];
+ uint8 ar2[4];
uint8 fld_1a;
uint8 modWheelImpact;
+ uint8 fld_1c;
+ uint32 fld_1d;
+ uint32 fld_21;
+ uint32 fld_25;
+ int8 dir;
+ uint32 fld_2a;
+ uint8 fld_2b;
+ uint8 fld_2c;
+ uint8 fld_2d;
uint8 modWheel;
} *_stateA;
@@ -83,7 +80,9 @@ private:
} *_stateB;
uint32 getEffectState(uint8 type);
- void processEffect(StateA *a, const uint8 *effectData);
+ void initEffect(StateA *a, const uint8 *effectData);
+ void updateEffect(StateA *a);
+ int lookupVolume(int a, int b);
void keyOn();
void keyOff();
@@ -101,7 +100,7 @@ private:
uint8 _sustainNoteOff;
uint32 _duration;
uint8 _fld_13;
- uint8 _prg;
+ uint8 _prg;
uint16 _freq;
int16 _freqAdjust;
@@ -111,6 +110,7 @@ private:
static const uint8 _chanMap[];
static const uint8 _chanMap2[];
static const uint8 _effectDefs[];
+ static const uint16 _effectData[];
static const uint8 _freqMSB[];
static const uint16 _freqLSB[];
};
@@ -327,14 +327,14 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec
break;
}
- processEffect(a, effectData);
+ initEffect(a, effectData);
}
void TownsMidiOutputChannel::setModWheel(uint8 value) {
- if (_stateA[0].active && _stateB[0].type)
+ if (_stateA[0].numLoop && _stateB[0].type)
_stateA[0].modWheel = value >> 2;
- if (_stateA[1].active && _stateB[1].type)
+ if (_stateA[1].numLoop && _stateB[1].type)
_stateA[1].modWheel = value >> 2;
}
@@ -393,8 +393,81 @@ uint32 TownsMidiOutputChannel::getEffectState(uint8 type) {
return res;
}
-void TownsMidiOutputChannel::processEffect(StateA *a, const uint8 *effectData) {
+void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) {
+ a->numLoop = 1;
+ a->fld_1 = 0;
+ a->fld_1c = 0x1f;
+ a->fld_5 = effectData[0];
+ a->ar1[0] = effectData[1];
+ a->ar1[1] = effectData[3];
+ a->ar1[2] = effectData[5];
+ a->ar1[3] = effectData[6];
+ a->ar2[0] = effectData[2];
+ a->ar2[1] = effectData[3];
+ a->ar2[2] = 0;
+ a->ar2[3] = effectData[7];
+ updateEffect(a);
+}
+
+void TownsMidiOutputChannel::updateEffect(StateA *a) {
+ uint8 c = --a->numLoop;
+ uint16 v = a->ar1[c];
+ int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->fld_1a]];
+
+ if (v & 0x80)
+ e = _driver->randomValue(e);
+
+ if (!e)
+ e = 1;
+
+ a->fld_1d = a->fld_21 = e;
+ int32 d = 0;
+ if (c + 1 != 3) {
+ v = a->ar2[c];
+ e = lookupVolume(a->fld_9, (v & 0x7f) - 31);
+
+ if (v & 0x80)
+ e = _driver->randomValue(e);
+
+ if (e + a->effectState > a->fld_9) {
+ e = a->fld_9 - a->effectState;
+ } else {
+ if (e + a->effectState + 1 <= 0)
+ e = -e;
+ }
+
+ d = e - a->fld_1;
+ }
+
+ a->fld_25 = d / a->fld_1d;
+ a->dir = d < 0 ? -1 : 1;
+ a->fld_2a = d % a->fld_1d;
+
+ a->fld_2b = a->fld_2c = a->fld_2d = a->modWheel = 0;
+}
+
+int TownsMidiOutputChannel::lookupVolume(int a, int b) {
+ if (b == 0)
+ return 0;
+
+ if (b == 31)
+ return a;
+
+ if (a > 63)
+ return ((a + 1) * b) >> 5;
+
+ if (b < 0) {
+ if (a < 0)
+ return _driver->_chanOutputLevel[(-a << 5) - b];
+ else
+ return -_driver->_chanOutputLevel[(a << 5) - b];
+ } else {
+ if (a < 0)
+ return -_driver->_chanOutputLevel[(-a << 5) + b];
+ else
+ return _driver->_chanOutputLevel[(-a << 5) + b];
+ }
}
void TownsMidiOutputChannel::keyOn() {
@@ -452,6 +525,13 @@ const uint8 TownsMidiOutputChannel::_effectDefs[] = {
0x20, 0x04, 0x10, 0x00, 0xC0, 0x00, 0x01, 0x00, 0xC0, 0x01, 0x0E, 0x00
};
+const uint16 TownsMidiOutputChannel::_effectData[] = {
+ 0x0001, 0x0002, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ 0x000A, 0x000C, 0x000E, 0x0010, 0x0012, 0x0015, 0x0018, 0x001E,
+ 0x0024, 0x0032, 0x0040, 0x0052, 0x0064, 0x0088, 0x00A0, 0x00C0,
+ 0x00F0, 0x0114, 0x0154, 0x01CC, 0x0258, 0x035C, 0x04B0, 0x0640
+};
+
const uint8 TownsMidiOutputChannel::_freqMSB[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -556,12 +636,12 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
if (_instrument[11] & 0x80)
oc->setupEffects(0, _instrument[11], &_instrument[12]);
else
- oc->_stateA[0].active = 0;
+ oc->_stateA[0].numLoop = 0;
if (_instrument[20] & 0x80)
oc->setupEffects(1, _instrument[20], &_instrument[21]);
else
- oc->_stateA[1].active = 0;
+ oc->_stateA[1].numLoop = 0;
}
void TownsMidiInputChannel::programChange(byte program) {
@@ -661,7 +741,7 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = {
0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F
};
-MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timerBpara(0), _open(false) {
+MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter(0), _curChan(0), _rand(1), _open(false) {
_intf = new TownsAudioInterface(mixer, this);
_channels = new TownsMidiInputChannel*[32];
@@ -681,9 +761,6 @@ MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerBproc(0), _timer
}
for (int i = 0; i < 64; i++)
_chanOutputLevel[i << 5] = 0;
-
- _tickCounter = 0;
- _curChan = 0;
}
MidiDriver_TOWNS::~MidiDriver_TOWNS() {
@@ -764,8 +841,8 @@ void MidiDriver_TOWNS::send(uint32 b) {
}
void MidiDriver_TOWNS::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
- _timerBproc = timer_proc;
- _timerBpara = timer_param;
+ _timerProc = timer_proc;
+ _timerProcPara = timer_param;
}
uint32 MidiDriver_TOWNS::getBaseTempo() {
@@ -792,12 +869,12 @@ void MidiDriver_TOWNS::timerCallback(int timerId) {
switch (timerId) {
case 1:
- if (_timerBproc) {
- _timerBproc(_timerBpara);
+ if (_timerProc) {
+ _timerProc(_timerProcPara);
_tickCounter += 10000;
while (_tickCounter >= 4167) {
_tickCounter -= 4167;
- _timerBproc(_timerBpara);
+ _timerProc(_timerProcPara);
}
}
break;
@@ -827,4 +904,9 @@ TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) {
res->disconnect();
return res;
+}
+
+int MidiDriver_TOWNS::randomValue(int para) {
+ _rand = (_rand & 1) ? (_rand >> 1) ^ 0xb8 : (_rand >> 1);
+ return (_rand * para) >> 8;
}
\ No newline at end of file
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index 005c77c..1a4a861 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -59,18 +59,21 @@ public:
private:
TownsMidiOutputChannel *allocateOutputChannel(int pri);
+
+ int randomValue(int para);
TownsMidiInputChannel **_channels;
TownsMidiOutputChannel **_out;
TownsMidiChanState *_chanState;
- Common::TimerManager::TimerProc _timerBproc;
- void *_timerBpara;
+ Common::TimerManager::TimerProc _timerProc;
+ void *_timerProcPara;
TownsAudioInterface *_intf;
uint32 _tickCounter;
uint8 _curChan;
+ uint8 _rand;
bool _open;
Commit: 17861037ba88f69548d5467e1f4f83d9e354498d
https://github.com/scummvm/scummvm/commit/17861037ba88f69548d5467e1f4f83d9e354498d
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:30-07:00
Commit Message:
MONKEY2 / INDY4 FM-TOWNS: set proper GUIO flags
Changed paths:
engines/scumm/detection_tables.h
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index 4234664..7eb1e80 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -184,6 +184,8 @@ using Common::GUIO_NOLAUNCHLOAD;
using Common::GUIO_NOMIDI;
using Common::GUIO_NOSPEECH;
using Common::GUIO_MIDITOWNS;
+using Common::GUIO_MIDIADLIB;
+using Common::GUIO_MIDIMT32;
// The following table contains information about variants of our various
// games. We index into it with help of md5table (from scumm-md5.h), to find
@@ -242,11 +244,11 @@ static const GameSettings gameVariantsTable[] = {
{"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO_NOSPEECH | GUIO_NOMIDI},
{"monkey2", "", 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH},
- {"monkey2", "FM-TOWNS", 0, GID_MONKEY2, 5, 0, MDT_TOWNS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, Common::kPlatformFMTowns, GUIO_NOSPEECH},
+ {"monkey2", "FM-TOWNS", 0, GID_MONKEY2, 5, 0, MDT_TOWNS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_MIDITOWNS | GUIO_MIDIADLIB | GUIO_MIDIMT32},
{"atlantis", "", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NONE},
{"atlantis", "Floppy", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH},
- {"atlantis", "FM-TOWNS", 0, GID_INDY4, 5, 0, MDT_TOWNS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, Common::kPlatformFMTowns, GUIO_NONE},
+ {"atlantis", "FM-TOWNS", 0, GID_INDY4, 5, 0, MDT_TOWNS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, Common::kPlatformFMTowns, GUIO_MIDITOWNS | GUIO_MIDIADLIB | GUIO_MIDIMT32},
{"tentacle", "", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE},
{"tentacle", "Floppy", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH},
Commit: 78130f940ff9047756a5d9a0e219e8d2bfa066eb
https://github.com/scummvm/scummvm/commit/78130f940ff9047756a5d9a0e219e8d2bfa066eb
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:32-07:00
Commit Message:
FM-TOWNS AUDIO: start fixing midi driver tempo
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_midi.h
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index ab1fdbc..095c7ba 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -40,6 +40,8 @@ public:
void connect(TownsMidiInputChannel *chan);
void disconnect();
+ bool update();
+
enum CheckPriorityStatus {
kDisconnected = -3,
kHighPriority = -2
@@ -81,7 +83,9 @@ private:
uint32 getEffectState(uint8 type);
void initEffect(StateA *a, const uint8 *effectData);
- void updateEffect(StateA *a);
+ void updateEffectOuter3(StateA *a, StateB *b);
+ void updateEffectOuter(StateA *a, StateB *b);
+ void updateEffect(StateA *a);
int lookupVolume(int a, int b);
void keyOn();
@@ -98,10 +102,8 @@ private:
uint8 _carrierTl;
uint8 _modulatorTl;
uint8 _sustainNoteOff;
- uint32 _duration;
- uint8 _fld_13;
- uint8 _prg;
-
+ int32 _duration;
+
uint16 _freq;
int16 _freqAdjust;
@@ -215,7 +217,7 @@ uint8 TownsMidiChanState::get(uint8 type) {
}
TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex),
- _midi(0), _prev(0), _next(0), _fld_c(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _fld_13(0), _prg(0), _freq(0), _freqAdjust(0) {
+ _midi(0), _prev(0), _next(0), _fld_c(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) {
_stateA = new StateA[2];
memset(_stateA, 0, 2 * sizeof(StateA));
_stateB = new StateB[2];
@@ -363,6 +365,24 @@ void TownsMidiOutputChannel::disconnect() {
_midi = 0;
}
+bool TownsMidiOutputChannel::update() {
+ if (!_midi)
+ return false;
+
+ _duration -= 17;
+ if (_duration <=0) {
+ disconnect();
+ return true;
+ }
+
+ for (int i = 0; i < 2; i++) {
+ if (_stateA[i].numLoop)
+ updateEffectOuter3(&_stateA[i], &_stateB[i]);
+ }
+
+ return false;
+}
+
int TownsMidiOutputChannel::checkPriority(int pri) {
if (!_midi)
return kDisconnected;
@@ -409,6 +429,14 @@ void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) {
updateEffect(a);
}
+void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) {
+
+}
+
+void TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
+
+}
+
void TownsMidiOutputChannel::updateEffect(StateA *a) {
uint8 c = --a->numLoop;
uint16 v = a->ar1[c];
@@ -741,7 +769,7 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = {
0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F
};
-MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter(0), _curChan(0), _rand(1), _open(false) {
+MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter1(0), _tickCounter2(0), _curChan(0), _rand(1), _open(false) {
_intf = new TownsAudioInterface(mixer, this);
_channels = new TownsMidiInputChannel*[32];
@@ -846,7 +874,7 @@ void MidiDriver_TOWNS::setTimerCallback(void *timer_param, Common::TimerManager:
}
uint32 MidiDriver_TOWNS::getBaseTempo() {
- return 4167;
+ return 10080;
}
MidiChannel *MidiDriver_TOWNS::allocateChannel() {
@@ -869,14 +897,14 @@ void MidiDriver_TOWNS::timerCallback(int timerId) {
switch (timerId) {
case 1:
- if (_timerProc) {
- _timerProc(_timerProcPara);
- _tickCounter += 10000;
- while (_tickCounter >= 4167) {
- _tickCounter -= 4167;
- _timerProc(_timerProcPara);
- }
- }
+ updateParser();
+ updateOutputChannels();
+
+ /*_tickCounter1 += 10000;
+ while (_tickCounter1 >= 4167) {
+ _tickCounter1 -= 4167;
+ unkUpdate();
+ }*/
break;
default:
break;
@@ -906,6 +934,23 @@ TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) {
return res;
}
+void MidiDriver_TOWNS::updateParser() {
+ if (_timerProc)
+ _timerProc(_timerProcPara);
+}
+
+void MidiDriver_TOWNS::updateOutputChannels() {
+ _tickCounter2 += 10000;
+ while (_tickCounter2 >= 16667) {
+ _tickCounter2 -= 16667;
+ for (int i = 0; i < 6; i++) {
+ TownsMidiOutputChannel *oc = _out[i];
+ if (oc->update())
+ return;
+ }
+ }
+}
+
int MidiDriver_TOWNS::randomValue(int para) {
_rand = (_rand & 1) ? (_rand >> 1) ^ 0xb8 : (_rand >> 1);
return (_rand * para) >> 8;
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index 1a4a861..a525226 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -59,7 +59,10 @@ public:
private:
TownsMidiOutputChannel *allocateOutputChannel(int pri);
-
+
+ void updateParser();
+ void updateOutputChannels();
+
int randomValue(int para);
TownsMidiInputChannel **_channels;
@@ -71,7 +74,8 @@ private:
TownsAudioInterface *_intf;
- uint32 _tickCounter;
+ uint32 _tickCounter1;
+ uint32 _tickCounter2;
uint8 _curChan;
uint8 _rand;
Commit: 214a70002f5c75ea6bd59e808b73a309039ddd74
https://github.com/scummvm/scummvm/commit/214a70002f5c75ea6bd59e808b73a309039ddd74
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:33-07:00
Commit Message:
FM-TOWNS AUDIO: fixed mod wheel setting
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 095c7ba..6ea9a72 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -59,18 +59,15 @@ private:
uint8 fld_11;
uint8 ar1[4];
uint8 ar2[4];
- uint8 fld_1a;
- uint8 modWheelImpact;
+ int8 modWheelSensitivity;
+ uint8 modWheelState;
uint8 fld_1c;
uint32 fld_1d;
uint32 fld_21;
uint32 fld_25;
int8 dir;
uint32 fld_2a;
- uint8 fld_2b;
- uint8 fld_2c;
- uint8 fld_2d;
- uint8 modWheel;
+ uint32 fld_2e;
} *_stateA;
struct StateB {
@@ -84,7 +81,7 @@ private:
uint32 getEffectState(uint8 type);
void initEffect(StateA *a, const uint8 *effectData);
void updateEffectOuter3(StateA *a, StateB *b);
- void updateEffectOuter(StateA *a, StateB *b);
+ int updateEffectOuter(StateA *a, StateB *b);
void updateEffect(StateA *a);
int lookupVolume(int a, int b);
@@ -306,8 +303,8 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec
b->fld_6 = c & 0x10;
b->type = para1[c & 0x0f];
a->fld_9 = maxVal[c & 0x0f];
- a->fld_1a = 0x1f;
- a->modWheelImpact = b->useModWheel ? _midi->_modWheel >> 2 : 0x1f;
+ a->modWheelSensitivity = 0x1f;
+ a->modWheelState = b->useModWheel ? _midi->_modWheel >> 2 : 0x1f;
switch (b->type) {
case 0:
@@ -318,11 +315,11 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec
break;
case 30:
a->effectState = 0x1f;
- b->a->modWheelImpact = 0;
+ b->a->modWheelState = 0;
break;
case 31:
a->effectState = 0;
- b->a->fld_1a = 0;
+ b->a->modWheelSensitivity = 0;
break;
default:
a->effectState = getEffectState(b->type);
@@ -334,10 +331,10 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec
void TownsMidiOutputChannel::setModWheel(uint8 value) {
if (_stateA[0].numLoop && _stateB[0].type)
- _stateA[0].modWheel = value >> 2;
+ _stateA[0].modWheelState = value >> 2;
if (_stateA[1].numLoop && _stateB[1].type)
- _stateA[1].modWheel = value >> 2;
+ _stateA[1].modWheelState = value >> 2;
}
void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) {
@@ -369,10 +366,12 @@ bool TownsMidiOutputChannel::update() {
if (!_midi)
return false;
- _duration -= 17;
- if (_duration <=0) {
- disconnect();
- return true;
+ if (_duration) {
+ _duration -= 17;
+ if (_duration <=0) {
+ disconnect();
+ return true;
+ }
}
for (int i = 0; i < 2; i++) {
@@ -433,14 +432,14 @@ void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) {
}
-void TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
-
+int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
+ return 0;
}
void TownsMidiOutputChannel::updateEffect(StateA *a) {
uint8 c = --a->numLoop;
uint16 v = a->ar1[c];
- int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->fld_1a]];
+ int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]];
if (v & 0x80)
e = _driver->randomValue(e);
@@ -471,8 +470,7 @@ void TownsMidiOutputChannel::updateEffect(StateA *a) {
a->fld_25 = d / a->fld_1d;
a->dir = d < 0 ? -1 : 1;
a->fld_2a = d % a->fld_1d;
-
- a->fld_2b = a->fld_2c = a->fld_2d = a->modWheel = 0;
+ a->fld_2e = 0;
}
int TownsMidiOutputChannel::lookupVolume(int a, int b) {
Commit: 41edb7c6b55417bf765d51c128e2e9747b3b72b2
https://github.com/scummvm/scummvm/commit/41edb7c6b55417bf765d51c128e2e9747b3b72b2
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:34-07:00
Commit Message:
FM-TOWNS AUDIO: some more midi driver code
Changed paths:
audio/softsynth/fmtowns_pc98/towns_audio.cpp
audio/softsynth/fmtowns_pc98/towns_midi.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
index 065532f..3360612 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -467,6 +467,7 @@ int TownsAudioInterfaceIntern::processCommand(int command, va_list &args) {
if (command < 0 || command > 81)
return 4;
+ Common::StackLock lock(_mutex);
return (this->*_intfOpcodes[command])(args);
}
@@ -918,7 +919,7 @@ int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) {
left = (left & 0x7e) >> 1;
right = (right & 0x7e) >> 1;
- if (chan)
+ if (chan == 12)
_outputVolumeFlags |= flags[chanType];
else
_outputVolumeFlags &= ~flags[chanType];
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 6ea9a72..fe7fce7 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -53,9 +53,9 @@ private:
struct StateA {
uint8 numLoop;
int32 fld_1;
- uint32 fld_5;
+ int32 duration;
int32 fld_9;
- int32 effectState;
+ int16 effectState;
uint8 fld_11;
uint8 ar1[4];
uint8 ar2[4];
@@ -63,7 +63,7 @@ private:
uint8 modWheelState;
uint8 fld_1c;
uint32 fld_1d;
- uint32 fld_21;
+ int32 fld_21;
uint32 fld_25;
int8 dir;
uint32 fld_2a;
@@ -71,14 +71,14 @@ private:
} *_stateA;
struct StateB {
- uint32 fld_0;
+ int8 inc;
uint8 type;
uint8 useModWheel;
uint8 fld_6;
StateA *a;
} *_stateB;
- uint32 getEffectState(uint8 type);
+ uint16 getEffectState(uint8 type);
void initEffect(StateA *a, const uint8 *effectData);
void updateEffectOuter3(StateA *a, StateB *b);
int updateEffectOuter(StateA *a, StateB *b);
@@ -292,19 +292,19 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v
void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effectData) {
uint16 maxVal[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F };
- uint8 para1[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 };
+ uint8 effectType[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 };
StateA *a = &_stateA[index];
StateB *b = &_stateB[index];
- b->fld_0 = 0;
+ b->inc = 0;
b->useModWheel = c & 0x40;
a->fld_11 = c & 0x20;
b->fld_6 = c & 0x10;
- b->type = para1[c & 0x0f];
+ b->type = effectType[c & 0x0f];
a->fld_9 = maxVal[c & 0x0f];
- a->modWheelSensitivity = 0x1f;
- a->modWheelState = b->useModWheel ? _midi->_modWheel >> 2 : 0x1f;
+ a->modWheelSensitivity = 31;
+ a->modWheelState = b->useModWheel ? _midi->_modWheel >> 2 : 31;
switch (b->type) {
case 0:
@@ -314,7 +314,7 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec
a->effectState = _modulatorTl;
break;
case 30:
- a->effectState = 0x1f;
+ a->effectState = 31;
b->a->modWheelState = 0;
break;
case 31:
@@ -392,7 +392,7 @@ int TownsMidiOutputChannel::checkPriority(int pri) {
return kHighPriority;
}
-uint32 TownsMidiOutputChannel::getEffectState(uint8 type) {
+uint16 TownsMidiOutputChannel::getEffectState(uint8 type) {
uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan);
if (type == 28)
@@ -415,8 +415,8 @@ uint32 TownsMidiOutputChannel::getEffectState(uint8 type) {
void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) {
a->numLoop = 1;
a->fld_1 = 0;
- a->fld_1c = 0x1f;
- a->fld_5 = effectData[0];
+ a->fld_1c = 31;
+ a->duration = effectData[0] * 63;
a->ar1[0] = effectData[1];
a->ar1[1] = effectData[3];
a->ar1[2] = effectData[5];
@@ -429,15 +429,80 @@ void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) {
}
void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) {
+ uint8 f = updateEffectOuter(a, b);
+
+ if (f & 1) {
+ switch (b->type) {
+ case 0:
+ _carrierTl = (a->effectState & 0xff) + b->inc; /*???*/
+ break;
+ case 13:
+ _modulatorTl = (a->effectState & 0xff) + b->inc; /*???*/
+ break;
+ case 30:
+ b->a->modWheelState = b->inc;
+ break;
+ case 31:
+ b->a->modWheelSensitivity = b->inc;
+ break;
+ default:
+ break;
+ }
+ }
+ if (f & 2) {
+ if (b->fld_6)
+ keyOn();
+ }
}
int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
- return 0;
+ if (a->duration) {
+ a->duration -= 17;
+ if (a->duration <= 0) {
+ a->numLoop = 0;
+ return 0;
+ }
+ }
+
+ int32 t = a->fld_1 + a->fld_25;
+
+ a->fld_2e += a->fld_2a;
+ if (a->fld_2e >= a->fld_1d) {
+ a->fld_2e -= a->fld_1d;
+ t += a->dir;
+ }
+
+ int retFlags = 0;
+
+ if (t != a->fld_1 || a->modWheelState != a->fld_1c) {
+ a->fld_1 = t;
+ a->fld_1c = a->modWheelState;
+ t = lookupVolume(t, a->modWheelState);
+ if (t != b->inc)
+ b->inc = t;
+ retFlags |= 1;
+ }
+
+ if (--a->fld_21 != 0)
+ return retFlags;
+
+ if (++a->numLoop > 4) {
+ if (a->fld_11 == 0) {
+ a->numLoop = 0;
+ return retFlags;
+ }
+ a->numLoop = 1;
+ retFlags |= 2;
+ }
+
+ updateEffect(a);
+
+ return retFlags;
}
void TownsMidiOutputChannel::updateEffect(StateA *a) {
- uint8 c = --a->numLoop;
+ uint8 c = a->numLoop - 1;
uint16 v = a->ar1[c];
int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]];
@@ -461,7 +526,7 @@ void TownsMidiOutputChannel::updateEffect(StateA *a) {
e = a->fld_9 - a->effectState;
} else {
if (e + a->effectState + 1 <= 0)
- e = -e;
+ e = -a->effectState;
}
d = e - a->fld_1;
@@ -646,7 +711,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
oc->_fld_c = _instrument[10] & 1;
oc->_note = note;
oc->_sustainNoteOff = 0;
- oc->_duration = _instrument[29] * 72;
+ oc->_duration = _instrument[29] * 63;
oc->_modulatorTl = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
if (oc->_modulatorTl > 63)
Commit: 232cb2410c99b2282b96584543d756041ed9bfbe
https://github.com/scummvm/scummvm/commit/232cb2410c99b2282b96584543d756041ed9bfbe
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:36-07:00
Commit Message:
FM-TOWNS AUDIO: improve thread safety
Changed paths:
audio/softsynth/fmtowns_pc98/towns_audio.cpp
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
index 3360612..51c2000 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -411,13 +411,13 @@ bool TownsAudioInterfaceIntern::checkPluginDriver(TownsAudioInterfacePluginDrive
if (_refCount <= 1)
return true;
- Common::StackLock lock(_mutex);
-
if (_drv) {
if (driver && driver != _drv)
return false;
} else {
+ lock();
_drv = driver;
+ unlock();
}
return true;
@@ -467,8 +467,11 @@ int TownsAudioInterfaceIntern::processCommand(int command, va_list &args) {
if (command < 0 || command > 81)
return 4;
- Common::StackLock lock(_mutex);
- return (this->*_intfOpcodes[command])(args);
+ lock();
+ int res = (this->*_intfOpcodes[command])(args);
+ unlock();
+
+ return res;
}
void TownsAudioInterfaceIntern::setMusicVolume(int volume) {
@@ -539,13 +542,11 @@ void TownsAudioInterfaceIntern::nextTickEx(int32 *buffer, uint32 bufferSize) {
}
void TownsAudioInterfaceIntern::timerCallbackA() {
- Common::StackLock lock(_mutex);
if (_drv && _ready)
_drv->timerCallback(0);
}
void TownsAudioInterfaceIntern::timerCallbackB() {
- Common::StackLock lock(_mutex);
if (_ready) {
if (_drv)
_drv->timerCallback(1);
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index fe7fce7..95ba1eb 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -52,7 +52,7 @@ public:
private:
struct StateA {
uint8 numLoop;
- int32 fld_1;
+ uint32 fld_1;
int32 duration;
int32 fld_9;
int16 effectState;
@@ -60,10 +60,10 @@ private:
uint8 ar1[4];
uint8 ar2[4];
int8 modWheelSensitivity;
- uint8 modWheelState;
+ int8 modWheelState;
uint8 fld_1c;
uint32 fld_1d;
- int32 fld_21;
+ uint32 fld_21;
uint32 fld_25;
int8 dir;
uint32 fld_2a;
@@ -71,14 +71,14 @@ private:
} *_stateA;
struct StateB {
- int8 inc;
+ int16 inc;
uint8 type;
uint8 useModWheel;
uint8 fld_6;
StateA *a;
} *_stateB;
- uint16 getEffectState(uint8 type);
+ int16 getEffectState(uint8 type);
void initEffect(StateA *a, const uint8 *effectData);
void updateEffectOuter3(StateA *a, StateB *b);
int updateEffectOuter(StateA *a, StateB *b);
@@ -159,7 +159,7 @@ private:
int8 _transpose;
uint8 _fld_1f;
int8 _detune;
- uint8 _modWheel;
+ int8 _modWheel;
uint8 _sustain;
uint8 _pitchBendFactor;
int16 _pitchBend;
@@ -392,7 +392,7 @@ int TownsMidiOutputChannel::checkPriority(int pri) {
return kHighPriority;
}
-uint16 TownsMidiOutputChannel::getEffectState(uint8 type) {
+int16 TownsMidiOutputChannel::getEffectState(uint8 type) {
uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan);
if (type == 28)
@@ -404,7 +404,7 @@ uint16 TownsMidiOutputChannel::getEffectState(uint8 type) {
else if (type > 12)
type -= 13;
- uint32 res = 0;
+ int32 res = 0;
uint8 cs = (_driver->_chanState[chan].get(_effectDefs[type * 4] >> 5) & _effectDefs[type * 4 + 2]) >> _effectDefs[type * 4 + 1];
if (_effectDefs[type * 4 + 3])
res = _effectDefs[type * 4 + 3] - cs;
@@ -422,7 +422,7 @@ void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) {
a->ar1[2] = effectData[5];
a->ar1[3] = effectData[6];
a->ar2[0] = effectData[2];
- a->ar2[1] = effectData[3];
+ a->ar2[1] = effectData[4];
a->ar2[2] = 0;
a->ar2[3] = effectData[7];
updateEffect(a);
@@ -434,10 +434,10 @@ void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) {
if (f & 1) {
switch (b->type) {
case 0:
- _carrierTl = (a->effectState & 0xff) + b->inc; /*???*/
+ _carrierTl = a->effectState + b->inc; /*???*/
break;
case 13:
- _modulatorTl = (a->effectState & 0xff) + b->inc; /*???*/
+ _modulatorTl = a->effectState + b->inc; /*???*/
break;
case 30:
b->a->modWheelState = b->inc;
@@ -504,7 +504,7 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
void TownsMidiOutputChannel::updateEffect(StateA *a) {
uint8 c = a->numLoop - 1;
uint16 v = a->ar1[c];
- int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]];
+ int32 e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]];
if (v & 0x80)
e = _driver->randomValue(e);
@@ -545,7 +545,7 @@ int TownsMidiOutputChannel::lookupVolume(int a, int b) {
if (b == 31)
return a;
- if (a > 63)
+ if (a > 63 || a < -63)
return ((a + 1) * b) >> 5;
if (b < 0) {
@@ -760,6 +760,10 @@ void TownsMidiInputChannel::controlChange(byte control, byte value) {
case 64:
controlSustain(value);
break;
+ case 123:
+ while (_outChan)
+ _outChan->disconnect();
+ break;
default:
break;
}
@@ -793,7 +797,7 @@ void TownsMidiInputChannel::controlVolume(byte value) {
uint16 v2 = value;
if (_chanIndex != 16) {
_ctrlVolume = value;
- v2 = value;
+ v2 = _player->getEffectiveVolume();
}
_tl = (v1 * v2) >> 7;*/
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
index 289cc95..e35da91 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
@@ -1145,7 +1145,7 @@ void TownsPC98_AudioDriver::loadMusicData(uint8 *data, bool loadPaused) {
reset();
- Common::StackLock lock(_mutex);
+ lock();
uint8 *src_a = _trackPtr = _musicBuffer = data;
for (uint8 i = 0; i < 3; i++) {
@@ -1176,6 +1176,7 @@ void TownsPC98_AudioDriver::loadMusicData(uint8 *data, bool loadPaused) {
_finishedChannelsFlag = _finishedSSGFlag = _finishedRhythmFlag = 0;
_musicPlaying = (loadPaused ? false : true);
+ unlock();
}
void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) {
@@ -1194,16 +1195,17 @@ void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) {
return;
}
- Common::StackLock lock(_mutex);
+ lock();
_sfxData = _sfxBuffer = data;
_sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]);
_sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]);
_sfxPlaying = true;
_finishedSfxFlag = 0;
+ unlock();
}
void TownsPC98_AudioDriver::reset() {
- Common::StackLock lock(_mutex);
+ lock();
_musicPlaying = false;
_sfxPlaying = false;
@@ -1230,13 +1232,13 @@ void TownsPC98_AudioDriver::reset() {
if (_rhythmChannel)
_rhythmChannel->reset();
#endif
+ unlock();
}
void TownsPC98_AudioDriver::fadeStep() {
if (!_musicPlaying)
return;
- Common::StackLock lock(_mutex);
for (int j = 0; j < _numChan; j++) {
if (_updateChannelsFlag & _channels[j]->_idFlag)
_channels[j]->fadeStep();
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
index 57ab8d9..9412538 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -837,8 +837,7 @@ TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) :
_hasPercussion(type == kType86 ? true : false),
_oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0),
_rtt(type == kTypeTowns ? 0x514767 : 0x5B8D80), _baserate(55125.0f / (float)mixer->getOutputRate()),
- _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255),
- _regProtectionFlag(false), _ready(false) {
+ _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _externLock(0), _ready(false) {
memset(&_timers[0], 0, sizeof(ChipTimer));
memset(&_timers[1], 0, sizeof(ChipTimer));
@@ -931,9 +930,9 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {
if (_regProtectionFlag || !_ready)
return;
- static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
+ lock();
- Common::StackLock lock(_mutex);
+ static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
uint8 h = regAddress & 0xf0;
uint8 l = (regAddress & 0x0f);
@@ -1081,6 +1080,7 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {
if (l == 0) {
c->frqTemp = (c->frqTemp & 0xff00) | value;
c->updateEnvelopeParameters = true;
+ c->fmIndex = (c->frqTemp >> 4 & 0x7f);
for (int i = 0; i < 4; i++)
co[i]->frequency(c->frqTemp);
} else if (l == 4) {
@@ -1112,18 +1112,17 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {
default:
warning("TownsPC98_FmSynth: UNKNOWN ADDRESS %d", regAddress);
}
+ unlock();
}
int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
- Common::StackLock lock(_mutex);
-
memset(buffer, 0, sizeof(int16) * numSamples);
int32 *tmp = new int32[numSamples];
int32 *tmpStart = tmp;
memset(tmp, 0, sizeof(int32) * numSamples);
int32 samplesLeft = numSamples >> 1;
- while (_ready && samplesLeft) {
+ while (_ready && !_externLock && samplesLeft) {
int32 render = samplesLeft;
for (int i = 0; i < 2; i++) {
@@ -1173,6 +1172,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
}
delete[] tmpStart;
+
return numSamples;
}
@@ -1187,7 +1187,7 @@ uint8 TownsPC98_FmSynth::readSSGStatus() {
}
void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) {
- Common::StackLock lock(_mutex);
+ lock();
_volumeA = CLIP<uint16>(volA, 0, Audio::Mixer::kMaxMixerVolume);
_volumeB = CLIP<uint16>(volB, 0, Audio::Mixer::kMaxMixerVolume);
if (_ssg)
@@ -1196,10 +1196,11 @@ void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) {
if (_prc)
_prc->setVolumeIntern(_volumeA, _volumeB);
#endif
+ unlock();
}
void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB) {
- Common::StackLock lock(_mutex);
+ lock();
_volMaskA = channelMaskA;
_volMaskB = channelMaskB;
if (_ssg)
@@ -1208,6 +1209,17 @@ void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB
if (_prc)
_prc->setVolumeChannelMasks(_volMaskA >> (_numChan + _numSSG), _volMaskB >> (_numChan + _numSSG));
#endif
+ unlock();
+}
+
+void TownsPC98_FmSynth::lock() {
+ _mutex.lock();
+ _externLock++;
+}
+
+void TownsPC98_FmSynth::unlock() {
+ _mutex.unlock();
+ _externLock--;
}
void TownsPC98_FmSynth::generateTables() {
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
index 5edd1a3..f1494b6 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
@@ -102,11 +102,13 @@ protected:
void setVolumeIntern(int volA, int volB);
void setVolumeChannelMasks(int channelMaskA, int channelMaskB);
+ void lock();
+ void unlock();
+
const int _numChan;
const int _numSSG;
const bool _hasPercussion;
- Common::Mutex _mutex;
private:
void generateTables();
void nextTick(int32 *buffer, uint32 bufferSize);
@@ -124,6 +126,7 @@ private:
}
uint16 frqTemp;
+ uint8 fmIndex;
bool enableLeft;
bool enableRight;
bool updateEnvelopeParameters;
@@ -179,6 +182,9 @@ private:
Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
+ int _externLock;
+ Common::Mutex _mutex;
+
#ifndef DISABLE_PC98_RHYTHM_CHANNEL
static const uint8 _percussionData[];
#endif
Commit: 66d19fde680c88bdc4be1656b88f0aa585e98a07
https://github.com/scummvm/scummvm/commit/66d19fde680c88bdc4be1656b88f0aa585e98a07
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:37-07:00
Commit Message:
FM-TOWNS AUDIO: some midi code fixes and some renaming
Changed paths:
audio/softsynth/fmtowns_pc98/towns_audio.cpp
audio/softsynth/fmtowns_pc98/towns_euphony.cpp
audio/softsynth/fmtowns_pc98/towns_euphony.h
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_midi.h
audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
engines/kyra/sound_towns.cpp
engines/scumm/player_towns.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
index 51c2000..6679e65 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -163,8 +163,10 @@ private:
int intf_fmReset(va_list &args);
int intf_setOutputVolume(va_list &args);
int intf_resetOutputVolume(va_list &args);
- int intf_updateOutputVolume(va_list &args);
+ int intf_setOutputMute(va_list &args);
int intf_cdaToggle(va_list &args);
+ int intf_getOutputVolume(va_list &args);
+ int intf_getOutputMute(va_list &args);
int intf_pcmUpdateEnvelopeGenerator(va_list &args);
int intf_notImpl(va_list &args);
@@ -344,13 +346,13 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA
// 68
INTCB(resetOutputVolume),
INTCB(notImpl),
- INTCB(updateOutputVolume),
+ INTCB(setOutputMute),
INTCB(notImpl),
// 72
INTCB(notImpl),
INTCB(cdaToggle),
- INTCB(notImpl),
- INTCB(notImpl),
+ INTCB(getOutputVolume),
+ INTCB(getOutputMute),
// 76
INTCB(notImpl),
INTCB(notImpl),
@@ -947,7 +949,7 @@ int TownsAudioInterfaceIntern::intf_resetOutputVolume(va_list &args) {
return 0;
}
-int TownsAudioInterfaceIntern::intf_updateOutputVolume(va_list &args) {
+int TownsAudioInterfaceIntern::intf_setOutputMute(va_list &args) {
int flags = va_arg(args, int);
_outputMuteFlags = flags & 3;
updateOutputVolume();
@@ -960,6 +962,14 @@ int TownsAudioInterfaceIntern::intf_cdaToggle(va_list &args) {
return 0;
}
+int TownsAudioInterfaceIntern::intf_getOutputVolume (va_list &args) {
+ return 0;
+}
+
+int TownsAudioInterfaceIntern::intf_getOutputMute (va_list &args) {
+ return 0;
+}
+
int TownsAudioInterfaceIntern::intf_pcmUpdateEnvelopeGenerator(va_list &args) {
for (int i = 0; i < 8; i++)
pcmUpdateEnvelopeGenerator(i);
diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
index cb6cfc5..f161228 100644
--- a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
@@ -27,7 +27,7 @@
TownsEuphonyDriver::TownsEuphonyDriver(Audio::Mixer *mixer) : _activeChannels(0), _sustainChannels(0),
_assignedChannels(0), _paraCount(0), _command(0), _tEnable(0), _tMode(0), _tOrdr(0), _tLevel(0),
- _tDetune(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0),
+ _tTranspose(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0),
_tempoControlMode(0) {
_para[0] = _para[1] = 0;
_intf = new TownsAudioInterface(mixer, this);
@@ -44,7 +44,7 @@ TownsEuphonyDriver::~TownsEuphonyDriver() {
delete[] _tMode;
delete[] _tOrdr;
delete[] _tLevel;
- delete[] _tDetune;
+ delete[] _tTranspose;
}
bool TownsEuphonyDriver::init() {
@@ -59,7 +59,7 @@ bool TownsEuphonyDriver::init() {
delete[] _tMode;
delete[] _tOrdr;
delete[] _tLevel;
- delete[] _tDetune;
+ delete[] _tTranspose;
_activeChannels = new int8[16];
_sustainChannels = new int8[16];
@@ -70,7 +70,7 @@ bool TownsEuphonyDriver::init() {
_tMode = new uint8[32];
_tOrdr = new uint8[32];
_tLevel = new int8[32];
- _tDetune = new int8[32];
+ _tTranspose = new int8[32];
reset();
@@ -250,11 +250,11 @@ int TownsEuphonyDriver::configChan_adjustVolume(int tableEntry, int val) {
return 0;
}
-int TownsEuphonyDriver::configChan_setDetune(int tableEntry, int val) {
+int TownsEuphonyDriver::configChan_setTranspose(int tableEntry, int val) {
if (tableEntry > 31)
return 3;
if (val <= 40)
- _tDetune[tableEntry] = (int8)(val & 0xff);
+ _tTranspose[tableEntry] = (int8)(val & 0xff);
return 0;
}
@@ -325,7 +325,7 @@ void TownsEuphonyDriver::resetTables() {
for (int i = 0; i < 32; i++)
_tOrdr[i] = i & 0x0f;
memset(_tLevel, 0, 32);
- memset(_tDetune, 0, 32);
+ memset(_tTranspose, 0, 32);
}
void TownsEuphonyDriver::resetTempo() {
@@ -672,7 +672,7 @@ bool TownsEuphonyDriver::evtSetupNote() {
uint8 velo = _musicPos[5];
sendEvent(mode, evt);
- sendEvent(mode, applyDetune(note));
+ sendEvent(mode, applyTranspose(note));
sendEvent(mode, applyVolumeAdjust(velo));
jumpNextLoop();
@@ -712,7 +712,7 @@ bool TownsEuphonyDriver::evtPolyphonicAftertouch() {
uint8 mode = _tMode[_musicPos[1]];
sendEvent(mode, evt);
- sendEvent(mode, applyDetune(_musicPos[4]));
+ sendEvent(mode, applyTranspose(_musicPos[4]));
sendEvent(mode, _musicPos[5]);
return false;
@@ -780,8 +780,8 @@ bool TownsEuphonyDriver::evtModeOrdrChange() {
return false;
}
-uint8 TownsEuphonyDriver::applyDetune(uint8 in) {
- int out = _tDetune[_musicPos[1]];
+uint8 TownsEuphonyDriver::applyTranspose(uint8 in) {
+ int out = _tTranspose[_musicPos[1]];
if (!out)
return in;
out += (in & 0x7f);
diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.h b/audio/softsynth/fmtowns_pc98/towns_euphony.h
index ae36d12..6b30bfb 100644
--- a/audio/softsynth/fmtowns_pc98/towns_euphony.h
+++ b/audio/softsynth/fmtowns_pc98/towns_euphony.h
@@ -59,7 +59,7 @@ public:
int configChan_setMode(int tableEntry, int val);
int configChan_remap(int tableEntry, int val);
int configChan_adjustVolume(int tableEntry, int val);
- int configChan_setDetune(int tableEntry, int val);
+ int configChan_setTranspose(int tableEntry, int val);
int assignChannel(int chan, int tableEntry);
@@ -111,7 +111,7 @@ private:
return false;
}
- uint8 applyDetune(uint8 in);
+ uint8 applyTranspose(uint8 in);
uint8 applyVolumeAdjust(uint8 in);
void sendNoteOff();
@@ -136,7 +136,7 @@ private:
uint8 *_tMode;
uint8 *_tOrdr;
int8 *_tLevel;
- int8 *_tDetune;
+ int8 *_tTranspose;
struct DlEvent {
uint8 evt;
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 95ba1eb..890c51a 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -24,6 +24,7 @@
#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
#include "common/textconsole.h"
+#include "common/system.h"
class TownsMidiOutputChannel {
friend class TownsMidiInputChannel;
@@ -33,8 +34,8 @@ public:
void noteOn(uint8 msb, uint16 lsb);
void noteOnPitchBend(uint8 msb, uint16 lsb);
- void setupProgram(const uint8 *data, uint8 vol1, uint8 vol2);
- void setupEffects(int index, uint8 c, const uint8 *effectData);
+ void setupProgram(const uint8 *data, uint8 mLevelPara, uint8 tLevelPara);
+ void setupEffects(int index, uint8 flags, const uint8 *effectData);
void setModWheel(uint8 value);
void connect(TownsMidiInputChannel *chan);
@@ -52,26 +53,26 @@ public:
private:
struct StateA {
uint8 numLoop;
- uint32 fld_1;
+ int32 fld_1;
int32 duration;
- int32 fld_9;
- int16 effectState;
+ uint32 fld_9;
+ int32 effectState;
uint8 fld_11;
uint8 ar1[4];
uint8 ar2[4];
int8 modWheelSensitivity;
int8 modWheelState;
- uint8 fld_1c;
- uint32 fld_1d;
+ uint8 modWheelLast;
+ uint16 fld_1d;
uint32 fld_21;
- uint32 fld_25;
+ int32 fld_25;
int8 dir;
uint32 fld_2a;
uint32 fld_2e;
} *_stateA;
struct StateB {
- int16 inc;
+ int32 inc;
uint8 type;
uint8 useModWheel;
uint8 fld_6;
@@ -99,7 +100,7 @@ private:
uint8 _carrierTl;
uint8 _modulatorTl;
uint8 _sustainNoteOff;
- int32 _duration;
+ int16 _duration;
uint16 _freq;
int16 _freqAdjust;
@@ -237,7 +238,7 @@ void TownsMidiOutputChannel::noteOnPitchBend(uint8 msb, uint16 lsb) {
keyOnSetFreq(_freq + _freqAdjust);
}
-void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 vol2) {
+void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, uint8 tLevelPara) {
// This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7),
// since it is just a modified AdLib driver. It also uses AdLib programs.
// There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS
@@ -248,10 +249,10 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v
uint8 chan = _chanMap[_chan];
uint8 mulAmsFms1 = _driver->_chanState[chan].mulAmsFms = data[0];
- uint8 tl1 = _driver->_chanState[chan].tl = (data[1] | 0x3f) - vol1;
+ uint8 tl1 = _driver->_chanState[chan].tl = (data[1] | 0x3f) - mLevelPara;
uint8 attDec1 = _driver->_chanState[chan].attDec = ~data[2];
uint8 sus1 = _driver->_chanState[chan].sus = ~data[3];
- uint8 unk1 = _driver->_chanState[chan].unk2 = data[4];
+ _driver->_chanState[chan].unk2 = data[4];
chan += 3;
out(0x30, mul[mulAmsFms1 & 0x0f]);
@@ -262,10 +263,10 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v
out(0x80, sus1);
uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = data[5];
- uint8 tl2 = _driver->_chanState[chan].tl = (data[6] | 0x3f) - vol2;
+ uint8 tl2 = _driver->_chanState[chan].tl = (data[6] | 0x3f) - tLevelPara;
uint8 attDec2 = _driver->_chanState[chan].attDec = ~data[7];
uint8 sus2 = _driver->_chanState[chan].sus = ~data[8];
- uint8 unk2 = _driver->_chanState[chan].unk2 = data[9];
+ _driver->_chanState[chan].unk2 = data[9];
uint8 mul2 = mul[mulAmsFms2 & 0x0f];
tl2 = (tl2 & 0x3f) + 15;
@@ -290,7 +291,7 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 vol1, uint8 v
out(0xb4, 0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5));
}
-void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effectData) {
+void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *effectData) {
uint16 maxVal[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F };
uint8 effectType[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 };
@@ -298,11 +299,11 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 c, const uint8 *effec
StateB *b = &_stateB[index];
b->inc = 0;
- b->useModWheel = c & 0x40;
- a->fld_11 = c & 0x20;
- b->fld_6 = c & 0x10;
- b->type = effectType[c & 0x0f];
- a->fld_9 = maxVal[c & 0x0f];
+ b->useModWheel = flags & 0x40;
+ a->fld_11 = flags & 0x20;
+ b->fld_6 = flags & 0x10;
+ b->type = effectType[flags & 0x0f];
+ a->fld_9 = maxVal[flags & 0x0f];
a->modWheelSensitivity = 31;
a->modWheelState = b->useModWheel ? _midi->_modWheel >> 2 : 31;
@@ -368,8 +369,9 @@ bool TownsMidiOutputChannel::update() {
if (_duration) {
_duration -= 17;
- if (_duration <=0) {
+ if (_duration <= 0) {
disconnect();
+ //_duration = 0;
return true;
}
}
@@ -415,7 +417,7 @@ int16 TownsMidiOutputChannel::getEffectState(uint8 type) {
void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) {
a->numLoop = 1;
a->fld_1 = 0;
- a->fld_1c = 31;
+ a->modWheelLast = 31;
a->duration = effectData[0] * 63;
a->ar1[0] = effectData[1];
a->ar1[1] = effectData[3];
@@ -475,16 +477,17 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
int retFlags = 0;
- if (t != a->fld_1 || a->modWheelState != a->fld_1c) {
+ if (t != a->fld_1 || a->modWheelState != a->modWheelLast) {
a->fld_1 = t;
- a->fld_1c = a->modWheelState;
+ a->modWheelLast = a->modWheelState;
t = lookupVolume(t, a->modWheelState);
if (t != b->inc)
b->inc = t;
retFlags |= 1;
}
- if (--a->fld_21 != 0)
+ --a->fld_21;/*???*/
+ if (a->fld_21 != 0)
return retFlags;
if (++a->numLoop > 4) {
@@ -504,7 +507,7 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
void TownsMidiOutputChannel::updateEffect(StateA *a) {
uint8 c = a->numLoop - 1;
uint16 v = a->ar1[c];
- int32 e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]];
+ int32 e = _effectData[_driver->_chanEffectLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]];
if (v & 0x80)
e = _driver->randomValue(e);
@@ -515,7 +518,7 @@ void TownsMidiOutputChannel::updateEffect(StateA *a) {
a->fld_1d = a->fld_21 = e;
int32 d = 0;
- if (c + 1 != 3) {
+ if (c != 2) {
v = a->ar2[c];
e = lookupVolume(a->fld_9, (v & 0x7f) - 31);
@@ -533,7 +536,8 @@ void TownsMidiOutputChannel::updateEffect(StateA *a) {
}
a->fld_25 = d / a->fld_1d;
- a->dir = d < 0 ? -1 : 1;
+ a->dir = (d < 0) ? -1 : 1;
+ d *= a->dir;
a->fld_2a = d % a->fld_1d;
a->fld_2e = 0;
}
@@ -550,14 +554,14 @@ int TownsMidiOutputChannel::lookupVolume(int a, int b) {
if (b < 0) {
if (a < 0)
- return _driver->_chanOutputLevel[(-a << 5) - b];
+ return _driver->_chanEffectLevel[((-a) << 5) - b];
else
- return -_driver->_chanOutputLevel[(a << 5) - b];
+ return -_driver->_chanEffectLevel[(a << 5) - b];
} else {
if (a < 0)
- return -_driver->_chanOutputLevel[(-a << 5) + b];
+ return -_driver->_chanEffectLevel[((-a) << 5) + b];
else
- return _driver->_chanOutputLevel[(-a << 5) + b];
+ return _driver->_chanEffectLevel[((-a) << 5) + b];
}
}
@@ -713,15 +717,15 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
oc->_sustainNoteOff = 0;
oc->_duration = _instrument[29] * 63;
- oc->_modulatorTl = (_instrument[1] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
+ oc->_modulatorTl = (_instrument[1] & 0x3f) + _driver->_chanEffectLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
if (oc->_modulatorTl > 63)
oc->_modulatorTl = 63;
- oc->_carrierTl = (_instrument[6] & 0x3f) + _driver->_chanOutputLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)];
+ oc->_carrierTl = (_instrument[6] & 0x3f) + _driver->_chanEffectLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)];
if (oc->_carrierTl > 63)
oc->_carrierTl = 63;
- oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanOutputLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]);
+ oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]);
oc->noteOn(note + _transpose, _freqLSB);
if (_instrument[11] & 0x80)
@@ -838,6 +842,19 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = {
MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter1(0), _tickCounter2(0), _curChan(0), _rand(1), _open(false) {
_intf = new TownsAudioInterface(mixer, this);
+}
+
+MidiDriver_TOWNS::~MidiDriver_TOWNS() {
+ close();
+ delete _intf;
+}
+
+int MidiDriver_TOWNS::open() {
+ if (_open)
+ return MERR_ALREADY_OPEN;
+
+ if (!_intf->init())
+ return MERR_CANNOT_CONNECT;
_channels = new TownsMidiInputChannel*[32];
for (int i = 0; i < 32; i++)
@@ -849,38 +866,13 @@ MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerP
_chanState = new TownsMidiChanState[32];
- _chanOutputLevel = new uint8[2048];
+ _chanEffectLevel = new uint8[2048];
for (int i = 0; i < 64; i++) {
for (int ii = 0; ii < 32; ii++)
- _chanOutputLevel[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff;
+ _chanEffectLevel[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff;
}
for (int i = 0; i < 64; i++)
- _chanOutputLevel[i << 5] = 0;
-}
-
-MidiDriver_TOWNS::~MidiDriver_TOWNS() {
- close();
- delete _intf;
- setTimerCallback(0, 0);
-
- for (int i = 0; i < 32; i++)
- delete _channels[i];
- delete[] _channels;
-
- for (int i = 0; i < 6; i++)
- delete _out[i];
- delete[] _out;
-
- delete[] _chanState;
- delete[] _chanOutputLevel;
-}
-
-int MidiDriver_TOWNS::open() {
- if (_open)
- return MERR_ALREADY_OPEN;
-
- if (!_intf->init())
- return MERR_CANNOT_CONNECT;
+ _chanEffectLevel[i << 5] = 0;
_intf->callback(0);
@@ -897,10 +889,38 @@ int MidiDriver_TOWNS::open() {
}
void MidiDriver_TOWNS::close() {
+ if (!_open)
+ return;
+
_open = false;
+
+ setTimerCallback(0, 0);
+ g_system->delayMillis(20);
+
+ if (_channels) {
+ for (int i = 0; i < 32; i++)
+ delete _channels[i];
+ delete[] _channels;
+ }
+ _channels = 0;
+
+ if (_out) {
+ for (int i = 0; i < 6; i++)
+ delete _out[i];
+ delete[] _out;
+ }
+ _out = 0;
+
+ delete[] _chanState;
+ _chanState = 0;
+ delete[] _chanEffectLevel;
+ _chanEffectLevel = 0;
}
void MidiDriver_TOWNS::send(uint32 b) {
+ if (!_open)
+ return;
+
byte param2 = (b >> 16) & 0xFF;
byte param1 = (b >> 8) & 0xFF;
byte cmd = b & 0xF0;
@@ -945,6 +965,9 @@ uint32 MidiDriver_TOWNS::getBaseTempo() {
}
MidiChannel *MidiDriver_TOWNS::allocateChannel() {
+ if (!_open)
+ return 0;
+
for (int i = 0; i < 32; ++i) {
TownsMidiInputChannel *chan = _channels[i];
if (chan->allocate())
@@ -978,6 +1001,23 @@ void MidiDriver_TOWNS::timerCallback(int timerId) {
}
}
+void MidiDriver_TOWNS::updateParser() {
+ if (_timerProc)
+ _timerProc(_timerProcPara);
+}
+
+void MidiDriver_TOWNS::updateOutputChannels() {
+ _tickCounter2 += 10000;
+ while (_tickCounter2 >= 16667) {
+ _tickCounter2 -= 16667;
+ for (int i = 0; i < 6; i++) {
+ TownsMidiOutputChannel *oc = _out[i];
+ if (oc->update())
+ return;
+ }
+ }
+}
+
TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) {
TownsMidiOutputChannel *res = 0;
@@ -1001,23 +1041,6 @@ TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) {
return res;
}
-void MidiDriver_TOWNS::updateParser() {
- if (_timerProc)
- _timerProc(_timerProcPara);
-}
-
-void MidiDriver_TOWNS::updateOutputChannels() {
- _tickCounter2 += 10000;
- while (_tickCounter2 >= 16667) {
- _tickCounter2 -= 16667;
- for (int i = 0; i < 6; i++) {
- TownsMidiOutputChannel *oc = _out[i];
- if (oc->update())
- return;
- }
- }
-}
-
int MidiDriver_TOWNS::randomValue(int para) {
_rand = (_rand & 1) ? (_rand >> 1) ^ 0xb8 : (_rand >> 1);
return (_rand * para) >> 8;
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index a525226..5164e04 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -43,25 +43,22 @@ public:
int open();
bool isOpen() const { return _open; }
void close();
+
void send(uint32 b);
- //virtual uint32 property(int prop, uint32 param) { return 0; }
- //virtual void sysEx(const byte *msg, uint16 length) { }
- //virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { }
- //virtual void metaEvent(byte type, byte *data, uint16 length) { }
+
void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
+
uint32 getBaseTempo();
MidiChannel *allocateChannel();
MidiChannel *getPercussionChannel();
void timerCallback(int timerId);
- TownsAudioInterface *intf() { return _intf; }
-
private:
- TownsMidiOutputChannel *allocateOutputChannel(int pri);
-
void updateParser();
void updateOutputChannels();
+
+ TownsMidiOutputChannel *allocateOutputChannel(int pri);
int randomValue(int para);
@@ -81,7 +78,7 @@ private:
bool _open;
- uint8 *_chanOutputLevel;
+ uint8 *_chanEffectLevel;
};
#endif
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
index 9412538..263986e 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -837,7 +837,7 @@ TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) :
_hasPercussion(type == kType86 ? true : false),
_oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0),
_rtt(type == kTypeTowns ? 0x514767 : 0x5B8D80), _baserate(55125.0f / (float)mixer->getOutputRate()),
- _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _externLock(0), _ready(false) {
+ _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _lock(0), _ready(false) {
memset(&_timers[0], 0, sizeof(ChipTimer));
memset(&_timers[1], 0, sizeof(ChipTimer));
@@ -1121,8 +1121,9 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
int32 *tmpStart = tmp;
memset(tmp, 0, sizeof(int32) * numSamples);
int32 samplesLeft = numSamples >> 1;
+ _lock |= 0x10000;
- while (_ready && !_externLock && samplesLeft) {
+ while (_ready && !(_lock & 0xffff) && samplesLeft) {
int32 render = samplesLeft;
for (int i = 0; i < 2; i++) {
@@ -1171,6 +1172,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
tmp += (render << 1);
}
+ _lock &= ~0x10000;
delete[] tmpStart;
return numSamples;
@@ -1178,6 +1180,8 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
void TownsPC98_FmSynth::deinit() {
_ready = false;
+ while (_lock)
+ g_system->delayMillis(20);
_mixer->stopHandle(_soundHandle);
_timers[0].cb = _timers[1].cb = &TownsPC98_FmSynth::idleTimerCallback;
}
@@ -1214,12 +1218,12 @@ void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB
void TownsPC98_FmSynth::lock() {
_mutex.lock();
- _externLock++;
+ _lock++;
}
void TownsPC98_FmSynth::unlock() {
_mutex.unlock();
- _externLock--;
+ _lock--;
}
void TownsPC98_FmSynth::generateTables() {
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
index f1494b6..cbf856c 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
@@ -182,7 +182,7 @@ private:
Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
- int _externLock;
+ int _lock;
Common::Mutex _mutex;
#ifndef DISABLE_PC98_RHYTHM_CHANNEL
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index 5f4e5a5..9a9892c 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -338,7 +338,7 @@ void SoundTowns::playEuphonyTrack(uint32 offset, int loop) {
for (int i = 0; i < 32; i++)
_driver->configChan_adjustVolume(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->configChan_setDetune(i, *src++);
+ _driver->configChan_setTranspose(i, *src++);
src = _musicTrackData + 1748;
for (int i = 0; i < 6; i++)
diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp
index f3b790a..5d49478 100644
--- a/engines/scumm/player_towns.cpp
+++ b/engines/scumm/player_towns.cpp
@@ -508,7 +508,7 @@ void Player_Towns_v1::playEuphonyTrack(int sound, const uint8 *data) {
for (int i = 0; i < 32; i++)
_driver->configChan_adjustVolume(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->configChan_setDetune(i, *src++);
+ _driver->configChan_setTranspose(i, *src++);
src += 8;
for (int i = 0; i < 6; i++)
Commit: e1ac2882bc214cc6198128f14f80b6f69b57215e
https://github.com/scummvm/scummvm/commit/e1ac2882bc214cc6198128f14f80b6f69b57215e
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:38-07:00
Commit Message:
SCUMM: add missing imuse feature
This adds an extra detune parameter which is assigned via sysex code 0. Most tracks don't use this (= assign a value of 0), so it isn't really a very noticeable feature.
Changed paths:
engines/scumm/imuse/imuse_internal.h
engines/scumm/imuse/imuse_part.cpp
engines/scumm/imuse/sysex_scumm.cpp
engines/scumm/saveload.h
engines/scumm/scumm.cpp
engines/scumm/sound.cpp
diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h
index ec60b22..b36bab4 100644
--- a/engines/scumm/imuse/imuse_internal.h
+++ b/engines/scumm/imuse/imuse_internal.h
@@ -302,7 +302,7 @@ struct Part : public Serializable {
byte _pitchbend_factor;
int8 _transpose, _transpose_eff;
byte _vol, _vol_eff;
- int8 _detune, _detune_eff;
+ int8 _detune, _sysexDetune, _detune_eff;
int8 _pan, _pan_eff;
bool _on;
byte _modwheel;
@@ -345,6 +345,7 @@ struct Part : public Serializable {
void set_transpose(int8 transpose);
void set_detune(int8 detune);
+ void set_sysexDetune(int8 detune);
void set_pri(int8 pri);
void set_pan(int8 pan);
diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp
index 808af23..8ccd6d5 100644
--- a/engines/scumm/imuse/imuse_part.cpp
+++ b/engines/scumm/imuse/imuse_part.cpp
@@ -72,6 +72,7 @@ void Part::saveLoadWithSerializer(Serializer *ser) {
MKLINE(Part, _transpose, sleInt8, VER(8)),
MKLINE(Part, _vol, sleUint8, VER(8)),
MKLINE(Part, _detune, sleInt8, VER(8)),
+ MKLINE(Part, _sysexDetune, sleInt8, VER(85)),
MKLINE(Part, _pan, sleInt8, VER(8)),
MKLINE(Part, _on, sleUint8, VER(8)),
MKLINE(Part, _modwheel, sleUint8, VER(8)),
@@ -110,7 +111,12 @@ void Part::saveLoadWithSerializer(Serializer *ser) {
}
void Part::set_detune(int8 detune) {
- _detune_eff = clamp((_detune = detune) + _player->getDetune(), -128, 127);
+ _detune_eff = clamp((_detune = detune) + _player->getDetune() + _sysexDetune, -128, 127);
+ sendPitchBend();
+}
+
+void Part::set_sysexDetune(int8 detune) {
+ _detune_eff = clamp((_sysexDetune = detune) + _player->getDetune() + _detune, -128, 127);
sendPitchBend();
}
@@ -277,7 +283,7 @@ void Part::setup(Player *player) {
_pan = clamp(player->getPan(), -64, 63);
_transpose_eff = player->getTranspose();
_transpose = 0;
- _detune = 0;
+ _detune = _sysexDetune = 0;
_detune_eff = player->getDetune();
_pitchbend_factor = 2;
_pitchbend = 0;
diff --git a/engines/scumm/imuse/sysex_scumm.cpp b/engines/scumm/imuse/sysex_scumm.cpp
index d6cf2e1..0295b74 100644
--- a/engines/scumm/imuse/sysex_scumm.cpp
+++ b/engines/scumm/imuse/sysex_scumm.cpp
@@ -72,6 +72,7 @@ void sysexHandler_Scumm(Player *player, const byte *msg, uint16 len) {
part->volume((p[5] & 0x0F) << 4 |(p[6] & 0x0F));
part->set_pan((p[7] & 0x0F) << 4 | (p[8] & 0x0F));
part->_percussion = player->_isMIDI ? ((p[9] & 0x08) > 0) : false;
+ part->set_sysexDetune((p[11] & 0x0F) << 4 | (p[12] & 0x0F));
part->pitchBendFactor((p[13] & 0x0F) << 4 | (p[14] & 0x0F));
if (part->_percussion) {
if (part->_mc) {
diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h
index 776f40e..792a31d 100644
--- a/engines/scumm/saveload.h
+++ b/engines/scumm/saveload.h
@@ -47,7 +47,7 @@ namespace Scumm {
* only saves/loads those which are valid for the version of the savegame
* which is being loaded/saved currently.
*/
-#define CURRENT_VER 84
+#define CURRENT_VER 85
/**
* An auxillary macro, used to specify savegame versions. We use this instead
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index b22a532..912bb87 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1834,12 +1834,8 @@ void ScummEngine::setupMusic(int midi) {
if (nativeMidiDriver != NULL && _native_mt32)
nativeMidiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
bool multi_midi = ConfMan.getBool("multi_midi") && _musicType != MDT_NONE && (midi & MDT_ADLIB);
- if (_musicType == MDT_ADLIB || multi_midi) {
- adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB));
- adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0);
- }
- if (_musicType == MDT_TOWNS) {
- adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_TOWNS));
+ if (_musicType == MDT_ADLIB || MDT_TOWNS || multi_midi) {
+ adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(_musicType == MDT_TOWNS ? MDT_TOWNS : MDT_ADLIB));
adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0);
}
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 9d14c16..c22da8e 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -1118,7 +1118,7 @@ int ScummEngine::readSoundResource(ResId idx) {
break;
case MKTAG('A','D','L',' '):
pri = 1;
- if (_musicType == MDT_ADLIB)
+ if (_musicType == MDT_ADLIB || _musicType == MDT_TOWNS)
pri = 10;
break;
case MKTAG('A','M','I',' '):
Commit: bbbde5aa6706237e2427757402d4a5757d767cd4
https://github.com/scummvm/scummvm/commit/bbbde5aa6706237e2427757402d4a5757d767cd4
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:40-07:00
Commit Message:
FM-TOWNS AUDIO: fix some midi driver bugs
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_midi.h
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 890c51a..824637e 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -44,8 +44,8 @@ public:
bool update();
enum CheckPriorityStatus {
- kDisconnected = -3,
- kHighPriority = -2
+ kDisconnected = -2,
+ kHighPriority = -1
};
int checkPriority(int pri);
@@ -55,14 +55,14 @@ private:
uint8 numLoop;
int32 fld_1;
int32 duration;
- uint32 fld_9;
+ uint16 fld_9;
int32 effectState;
uint8 fld_11;
uint8 ar1[4];
uint8 ar2[4];
int8 modWheelSensitivity;
int8 modWheelState;
- uint8 modWheelLast;
+ int8 modWheelLast;
uint16 fld_1d;
uint32 fld_21;
int32 fld_25;
@@ -91,10 +91,10 @@ private:
void keyOnSetFreq(uint16 frq);
void out(uint8 reg, uint8 val);
- TownsMidiInputChannel *_midi;
+ TownsMidiInputChannel *_in;
TownsMidiOutputChannel *_prev;
TownsMidiOutputChannel *_next;
- uint8 _fld_c;
+ uint8 _adjustModTl;
uint8 _chan;
uint8 _note;
uint8 _carrierTl;
@@ -145,7 +145,7 @@ private:
void releasePedal();
- TownsMidiOutputChannel *_outChan;
+ TownsMidiOutputChannel *_out;
uint8 *_instrument;
uint8 _prg;
@@ -215,11 +215,13 @@ uint8 TownsMidiChanState::get(uint8 type) {
}
TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex),
- _midi(0), _prev(0), _next(0), _fld_c(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) {
+ _in(0), _prev(0), _next(0), _adjustModTl(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) {
_stateA = new StateA[2];
memset(_stateA, 0, 2 * sizeof(StateA));
_stateB = new StateB[2];
memset(_stateB, 0, 2 * sizeof(StateB));
+ _stateB[0].a = &_stateA[1];
+ _stateB[1].a = &_stateA[0];
}
TownsMidiOutputChannel::~TownsMidiOutputChannel() {
@@ -259,7 +261,7 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, u
out(0x40, (tl1 & 0x3f) + 15);
out(0x50, ((attDec1 >> 4) << 1) | ((attDec1 >> 4) & 1));
out(0x60, ((attDec1 << 1) | (attDec1 & 1)) & 0x1f);
- out(0x70, (mulAmsFms1 & 0x20) ^ 0x20 ? ((sus1 & 0x0f) << 1) | 1: 0);
+ out(0x70, (mulAmsFms1 & 0x20) ^ 0x20 ? (((sus1 & 0x0f) << 1) | 1) : 0);
out(0x80, sus1);
uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = data[5];
@@ -272,7 +274,7 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, u
tl2 = (tl2 & 0x3f) + 15;
uint8 ar2 = ((attDec2 >> 4) << 1) | ((attDec2 >> 4) & 1);
uint8 dec2 = ((attDec2 << 1) | (attDec2 & 1)) & 0x1f;
- uint8 sus2r = (mulAmsFms2 & 0x20) ^ 0x20 ? ((sus2 & 0x0f) << 1) | 1: 0;
+ uint8 sus2r = (mulAmsFms2 & 0x20) ^ 0x20 ? (((sus2 & 0x0f) << 1) | 1) : 0;
for (int i = 4; i < 16; i += 4) {
out(0x30 + i, mul2);
@@ -284,11 +286,12 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, u
}
_driver->_chanState[chan].fgAlg = data[10];
+
uint8 alg = 5 + 2 * (data[10] & 1);
uint8 fb = 4 * (data[10] & 0x0e);
out(0xb0, fb | alg);
uint8 t = mulAmsFms1 | mulAmsFms2;
- out(0xb4, 0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5));
+ out(0xb4, (0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5)));
}
void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *effectData) {
@@ -305,7 +308,7 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *e
b->type = effectType[flags & 0x0f];
a->fld_9 = maxVal[flags & 0x0f];
a->modWheelSensitivity = 31;
- a->modWheelState = b->useModWheel ? _midi->_modWheel >> 2 : 31;
+ a->modWheelState = b->useModWheel ? _in->_modWheel >> 2 : 31;
switch (b->type) {
case 0:
@@ -341,16 +344,18 @@ void TownsMidiOutputChannel::setModWheel(uint8 value) {
void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) {
if (!chan)
return;
- _midi = chan;
- _next = chan->_outChan;
+
+ _in = chan;
+ _next = chan->_out;
_prev = 0;
- chan->_outChan = this;
+ chan->_out = this;
if (_next)
_next->_prev = this;
}
void TownsMidiOutputChannel::disconnect() {
keyOff();
+
TownsMidiOutputChannel *p = _prev;
TownsMidiOutputChannel *n = _next;
@@ -359,19 +364,18 @@ void TownsMidiOutputChannel::disconnect() {
if (p)
p->_next = n;
else
- _midi->_outChan = n;
- _midi = 0;
+ _in->_out = n;
+ _in = 0;
}
bool TownsMidiOutputChannel::update() {
- if (!_midi)
+ if (!_in)
return false;
if (_duration) {
_duration -= 17;
if (_duration <= 0) {
disconnect();
- //_duration = 0;
return true;
}
}
@@ -385,11 +389,11 @@ bool TownsMidiOutputChannel::update() {
}
int TownsMidiOutputChannel::checkPriority(int pri) {
- if (!_midi)
+ if (!_in)
return kDisconnected;
- if (!_next && pri >= _midi->_priority)
- return _midi->_priority;
+ if (!_next && pri >= _in->_priority)
+ return _in->_priority;
return kHighPriority;
}
@@ -486,12 +490,11 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
retFlags |= 1;
}
- --a->fld_21;/*???*/
- if (a->fld_21 != 0)
+ if (--a->fld_21)
return retFlags;
if (++a->numLoop > 4) {
- if (a->fld_11 == 0) {
+ if (!a->fld_11) {
a->numLoop = 0;
return retFlags;
}
@@ -506,7 +509,7 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
void TownsMidiOutputChannel::updateEffect(StateA *a) {
uint8 c = a->numLoop - 1;
- uint16 v = a->ar1[c];
+ uint8 v = a->ar1[c];
int32 e = _effectData[_driver->_chanEffectLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]];
if (v & 0x80)
@@ -665,7 +668,7 @@ const uint16 TownsMidiOutputChannel::_freqLSB[] = {
0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B
};
-TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _outChan(0), _prg(0), _chanIndex(chanIndex),
+TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _out(0), _prg(0), _chanIndex(chanIndex),
_effectLevel(0), _priority(0), _ctrlVolume(0), _tl(0), _pan(0), _panEff(0), _transpose(0), _percS(0), _pitchBendFactor(0), _pitchBend(0), _sustain(0), _freqLSB(0),
_fld_1f(0), _detune(0), _modWheel(0), _allocated(false) {
_instrument = new uint8[30];
@@ -692,16 +695,16 @@ void TownsMidiInputChannel::send(uint32 b) {
}
void TownsMidiInputChannel::noteOff(byte note) {
- if (!_outChan)
+ if (!_out)
return;
- if (_outChan->_note != note)
+ if (_out->_note != note)
return;
if (_sustain)
- _outChan->_sustainNoteOff = 1;
+ _out->_sustainNoteOff = 1;
else
- _outChan->disconnect();
+ _out->disconnect();
}
void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
@@ -712,7 +715,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
oc->connect(this);
- oc->_fld_c = _instrument[10] & 1;
+ oc->_adjustModTl = _instrument[10] & 1;
oc->_note = note;
oc->_sustainNoteOff = 0;
oc->_duration = _instrument[29] * 63;
@@ -725,7 +728,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
if (oc->_carrierTl > 63)
oc->_carrierTl = 63;
- oc->setupProgram(_instrument, oc->_fld_c == 1 ? _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]);
+ oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]);
oc->noteOn(note + _transpose, _freqLSB);
if (_instrument[11] & 0x80)
@@ -736,7 +739,7 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
if (_instrument[20] & 0x80)
oc->setupEffects(1, _instrument[20], &_instrument[21]);
else
- oc->_stateA[1].numLoop = 0;
+ oc->_stateA[1].numLoop = 0;
}
void TownsMidiInputChannel::programChange(byte program) {
@@ -746,8 +749,8 @@ void TownsMidiInputChannel::programChange(byte program) {
void TownsMidiInputChannel::pitchBend(int16 bend) {
_pitchBend = bend;
_freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune;
- for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next)
- oc->noteOnPitchBend(oc->_note + oc->_midi->_transpose, _freqLSB);
+ for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next)
+ oc->noteOnPitchBend(oc->_note + oc->_in->_transpose, _freqLSB);
}
void TownsMidiInputChannel::controlChange(byte control, byte value) {
@@ -765,8 +768,8 @@ void TownsMidiInputChannel::controlChange(byte control, byte value) {
controlSustain(value);
break;
case 123:
- while (_outChan)
- _outChan->disconnect();
+ while (_out)
+ _out->disconnect();
break;
default:
break;
@@ -776,8 +779,8 @@ void TownsMidiInputChannel::controlChange(byte control, byte value) {
void TownsMidiInputChannel::pitchBendFactor(byte value) {
_pitchBendFactor = value;
_freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune;
- for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next)
- oc->noteOnPitchBend(oc->_note + oc->_midi->_transpose, _freqLSB);
+ for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next)
+ oc->noteOnPitchBend(oc->_note + oc->_in->_transpose, _freqLSB);
}
void TownsMidiInputChannel::priority(byte value) {
@@ -790,7 +793,7 @@ void TownsMidiInputChannel::sysEx_customInstrument(uint32 type, const byte *inst
void TownsMidiInputChannel::controlModulationWheel(byte value) {
_modWheel = value;
- for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next)
+ for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next)
oc->setModWheel(value);
}
@@ -808,7 +811,7 @@ void TownsMidiInputChannel::controlVolume(byte value) {
_tl = value;
/* nullsub
- _outChan->setVolume(_tl);
+ _out->setVolume(_tl);
*/
}
@@ -823,7 +826,7 @@ void TownsMidiInputChannel::controlSustain(byte value) {
}
void TownsMidiInputChannel::releasePedal() {
- for (TownsMidiOutputChannel *oc = _outChan; oc; oc = oc->_next) {
+ for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next) {
if (oc->_sustainNoteOff)
oc->disconnect();
}
@@ -840,7 +843,7 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = {
0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F
};
-MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _tickCounter1(0), _tickCounter2(0), _curChan(0), _rand(1), _open(false) {
+MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _open(false) {
_intf = new TownsAudioInterface(mixer, this);
}
@@ -883,6 +886,10 @@ int MidiDriver_TOWNS::open() {
_intf->callback(33, 8);
_intf->setSoundEffectChanMask(~0x3f);
+ _tickCounter1 = _tickCounter2 = 0;
+ _allocCurPos = 0;
+ _rand = 1;
+
_open = true;
return 0;
@@ -978,7 +985,7 @@ MidiChannel *MidiDriver_TOWNS::allocateChannel() {
}
MidiChannel *MidiDriver_TOWNS::getPercussionChannel() {
- return 0;//_channels[16];
+ return 0;
}
void MidiDriver_TOWNS::timerCallback(int timerId) {
@@ -1018,20 +1025,20 @@ void MidiDriver_TOWNS::updateOutputChannels() {
}
}
-TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(int pri) {
+TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(uint8 pri) {
TownsMidiOutputChannel *res = 0;
for (int i = 0; i < 6; i++) {
- if (++_curChan == 6)
- _curChan = 0;
+ if (++_allocCurPos == 6)
+ _allocCurPos = 0;
- int s = _out[i]->checkPriority(pri);
+ int s = _out[_allocCurPos]->checkPriority(pri);
if (s == TownsMidiOutputChannel::kDisconnected)
- return _out[i];
+ return _out[_allocCurPos];
if (s != TownsMidiOutputChannel::kHighPriority) {
pri = s;
- res = _out[i];
+ res = _out[_allocCurPos];
}
}
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index 5164e04..8dc71f3 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -58,7 +58,7 @@ private:
void updateParser();
void updateOutputChannels();
- TownsMidiOutputChannel *allocateOutputChannel(int pri);
+ TownsMidiOutputChannel *allocateOutputChannel(uint8 pri);
int randomValue(int para);
@@ -73,7 +73,7 @@ private:
uint32 _tickCounter1;
uint32 _tickCounter2;
- uint8 _curChan;
+ uint8 _allocCurPos;
uint8 _rand;
bool _open;
Commit: 73d5b9f595ce5ce3794e5c4b1efc1dac6ed87af8
https://github.com/scummvm/scummvm/commit/73d5b9f595ce5ce3794e5c4b1efc1dac6ed87af8
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:41-07:00
Commit Message:
FM-TOWNS AUDIO: fix note off event in midi driver
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 824637e..addcf1a 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -569,11 +569,7 @@ int TownsMidiOutputChannel::lookupVolume(int a, int b) {
}
void TownsMidiOutputChannel::keyOn() {
- // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7),
- // since it is just a modified AdLib driver. It also uses AdLib programs.
- // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS
- // music being so bad compared to AdLib (unsuitable data is just forced into the
- // wrong audio device).
+ // This driver uses only 2 operators since it is just a modified AdLib driver.
out(0x28, 0x30);
}
@@ -587,11 +583,7 @@ void TownsMidiOutputChannel::keyOnSetFreq(uint16 frq) {
out(0xa4, frq >> 8);
out(0xa0, frq & 0xff);
out(0x28, 0);
- // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7),
- // since it is just a modified AdLib driver. It also uses AdLib programs.
- // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS
- // music being so bad compared to AdLib (unsuitable data is just forced into the
- // wrong audio device).
+ // This driver uses only 2 operators since it is just a modified AdLib driver.
out(0x28, 0x30);
}
@@ -698,13 +690,15 @@ void TownsMidiInputChannel::noteOff(byte note) {
if (!_out)
return;
- if (_out->_note != note)
- return;
+ for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next) {
+ if (oc->_note != note)
+ continue;
- if (_sustain)
- _out->_sustainNoteOff = 1;
- else
- _out->disconnect();
+ if (_sustain)
+ oc->_sustainNoteOff = 1;
+ else
+ oc->disconnect();
+ }
}
void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
@@ -743,7 +737,9 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
}
void TownsMidiInputChannel::programChange(byte program) {
- // Dysfunctional since this is all done inside the imuse code
+ // Not implemented (The loading and assignment of programs
+ // is handled externally by the SCUMM engine. The programs
+ // get sent via sysEx_customInstrument.)
}
void TownsMidiInputChannel::pitchBend(int16 bend) {
@@ -816,7 +812,7 @@ void TownsMidiInputChannel::controlVolume(byte value) {
}
void TownsMidiInputChannel::controlPanPos(byte value) {
- // not supported
+ // not implemented
}
void TownsMidiInputChannel::controlSustain(byte value) {
Commit: 13497a9b0fa27431bc74cc5340c6b991586ea09d
https://github.com/scummvm/scummvm/commit/13497a9b0fa27431bc74cc5340c6b991586ea09d
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:42-07:00
Commit Message:
SCUMM: fix recent commit (proper initialize new detune parameter)
Changed paths:
engines/scumm/imuse/imuse_part.cpp
diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp
index 8ccd6d5..8815757 100644
--- a/engines/scumm/imuse/imuse_part.cpp
+++ b/engines/scumm/imuse/imuse_part.cpp
@@ -49,6 +49,7 @@ Part::Part() {
_vol = 0;
_vol_eff = 0;
_detune = 0;
+ _sysexDetune = 0;
_detune_eff = 0;
_pan = 0;
_pan_eff = 0;
Commit: f9eb329c791e656ea474b9affd83a855be6e5b8a
https://github.com/scummvm/scummvm/commit/f9eb329c791e656ea474b9affd83a855be6e5b8a
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:44-07:00
Commit Message:
FM-TOWNS AUDIO: fix some bugs and rename some stuff in the midi driver code
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_midi.h
audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index addcf1a..f467952 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -51,40 +51,40 @@ public:
int checkPriority(int pri);
private:
- struct StateA {
- uint8 numLoop;
- int32 fld_1;
+ struct EffectState {
+ uint8 envState;
+ int32 envStepLen;
int32 duration;
- uint16 fld_9;
- int32 effectState;
- uint8 fld_11;
- uint8 ar1[4];
- uint8 ar2[4];
+ int32 envTargetLevel;
+ int32 currentLevel;
+ uint8 loop;
+ uint8 envStepping[4];
+ uint8 envMod[4];
int8 modWheelSensitivity;
int8 modWheelState;
int8 modWheelLast;
- uint16 fld_1d;
- uint32 fld_21;
- int32 fld_25;
+ uint16 envStateNumSteps;
+ uint32 envStateStepCounter;
+ int32 envChangePerStep;
int8 dir;
- uint32 fld_2a;
- uint32 fld_2e;
- } *_stateA;
+ uint32 envChangePerStepRem;
+ uint32 envChangeCountRem;
+ } *_effectStates;
- struct StateB {
- int32 inc;
+ struct EffectDef {
+ int32 phase;
uint8 type;
uint8 useModWheel;
- uint8 fld_6;
- StateA *a;
- } *_stateB;
+ uint8 loopRefresh;
+ EffectState *s;
+ } *_effectDefs;
- int16 getEffectState(uint8 type);
- void initEffect(StateA *a, const uint8 *effectData);
- void updateEffectOuter3(StateA *a, StateB *b);
- int updateEffectOuter(StateA *a, StateB *b);
- void updateEffect(StateA *a);
- int lookupVolume(int a, int b);
+ int16 getEffectLevel(uint8 type);
+ void initEffect(EffectState *s, const uint8 *effectData);
+ void updateEffectGenerator(EffectState *s, EffectDef *d);
+ int updateEffectEnvelope(EffectState *s, EffectDef *d);
+ void updateEffect(EffectState *s);
+ int calcModWheelLevel(int lvl, int mod);
void keyOn();
void keyOff();
@@ -97,8 +97,8 @@ private:
uint8 _adjustModTl;
uint8 _chan;
uint8 _note;
- uint8 _carrierTl;
- uint8 _modulatorTl;
+ uint8 _operator2Tl;
+ uint8 _operator1Tl;
uint8 _sustainNoteOff;
int16 _duration;
@@ -109,8 +109,8 @@ private:
static const uint8 _chanMap[];
static const uint8 _chanMap2[];
- static const uint8 _effectDefs[];
- static const uint16 _effectData[];
+ static const uint8 _effectDefaults[];
+ static const uint16 _effectEnvStepTable[];
static const uint8 _freqMSB[];
static const uint16 _freqLSB[];
};
@@ -215,18 +215,19 @@ uint8 TownsMidiChanState::get(uint8 type) {
}
TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex),
- _in(0), _prev(0), _next(0), _adjustModTl(0), _carrierTl(0), _note(0), _modulatorTl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) {
- _stateA = new StateA[2];
- memset(_stateA, 0, 2 * sizeof(StateA));
- _stateB = new StateB[2];
- memset(_stateB, 0, 2 * sizeof(StateB));
- _stateB[0].a = &_stateA[1];
- _stateB[1].a = &_stateA[0];
+ _in(0), _prev(0), _next(0), _adjustModTl(0), _operator2Tl(0), _note(0), _operator1Tl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) {
+ _effectStates = new EffectState[2];
+ _effectDefs = new EffectDef[2];
+
+ memset(_effectStates, 0, 2 * sizeof(EffectState));
+ memset(_effectDefs, 0, 2 * sizeof(EffectDef));
+ _effectDefs[0].s = &_effectStates[1];
+ _effectDefs[1].s = &_effectStates[0];
}
TownsMidiOutputChannel::~TownsMidiOutputChannel() {
- delete[] _stateA;
- delete[] _stateB;
+ delete[] _effectStates;
+ delete[] _effectDefs;
}
void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) {
@@ -243,9 +244,8 @@ void TownsMidiOutputChannel::noteOnPitchBend(uint8 msb, uint16 lsb) {
void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, uint8 tLevelPara) {
// This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7),
// since it is just a modified AdLib driver. It also uses AdLib programs.
- // There are no FM-TOWNS specific programs. This is the reason for the FM-TOWNS
- // music being so bad compared to AdLib (unsuitable data is just forced into the
- // wrong audio device).
+ // There are no FM-TOWNS specific programs. This is the reason for the low quality of the FM-TOWNS
+ // music (unsuitable data is just forced into the wrong audio device).
static const uint8 mul[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 };
uint8 chan = _chanMap[_chan];
@@ -295,50 +295,50 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, u
}
void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *effectData) {
- uint16 maxVal[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F };
+ uint16 effectTargetLevel[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F };
uint8 effectType[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 };
- StateA *a = &_stateA[index];
- StateB *b = &_stateB[index];
-
- b->inc = 0;
- b->useModWheel = flags & 0x40;
- a->fld_11 = flags & 0x20;
- b->fld_6 = flags & 0x10;
- b->type = effectType[flags & 0x0f];
- a->fld_9 = maxVal[flags & 0x0f];
- a->modWheelSensitivity = 31;
- a->modWheelState = b->useModWheel ? _in->_modWheel >> 2 : 31;
-
- switch (b->type) {
+ EffectState *s = &_effectStates[index];
+ EffectDef *d = &_effectDefs[index];
+
+ d->phase = 0;
+ d->useModWheel = flags & 0x40;
+ s->loop = flags & 0x20;
+ d->loopRefresh = flags & 0x10;
+ d->type = effectType[flags & 0x0f];
+ s->envTargetLevel = effectTargetLevel[flags & 0x0f];
+ s->modWheelSensitivity = 31;
+ s->modWheelState = d->useModWheel ? _in->_modWheel >> 2 : 31;
+
+ switch (d->type) {
case 0:
- a->effectState = _carrierTl;
+ s->currentLevel = _operator2Tl;
break;
case 13:
- a->effectState = _modulatorTl;
+ s->currentLevel = _operator1Tl;
break;
case 30:
- a->effectState = 31;
- b->a->modWheelState = 0;
+ s->currentLevel = 31;
+ d->s->modWheelState = 0;
break;
case 31:
- a->effectState = 0;
- b->a->modWheelSensitivity = 0;
+ s->currentLevel = 0;
+ d->s->modWheelSensitivity = 0;
break;
default:
- a->effectState = getEffectState(b->type);
+ s->currentLevel = getEffectLevel(d->type);
break;
}
- initEffect(a, effectData);
+ initEffect(s, effectData);
}
void TownsMidiOutputChannel::setModWheel(uint8 value) {
- if (_stateA[0].numLoop && _stateB[0].type)
- _stateA[0].modWheelState = value >> 2;
+ if (_effectStates[0].envState && _effectDefs[0].type)
+ _effectStates[0].modWheelState = value >> 2;
- if (_stateA[1].numLoop && _stateB[1].type)
- _stateA[1].modWheelState = value >> 2;
+ if (_effectStates[1].envState && _effectDefs[1].type)
+ _effectStates[1].modWheelState = value >> 2;
}
void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) {
@@ -381,8 +381,8 @@ bool TownsMidiOutputChannel::update() {
}
for (int i = 0; i < 2; i++) {
- if (_stateA[i].numLoop)
- updateEffectOuter3(&_stateA[i], &_stateB[i]);
+ if (_effectStates[i].envState)
+ updateEffectGenerator(&_effectStates[i], &_effectDefs[i]);
}
return false;
@@ -398,7 +398,7 @@ int TownsMidiOutputChannel::checkPriority(int pri) {
return kHighPriority;
}
-int16 TownsMidiOutputChannel::getEffectState(uint8 type) {
+int16 TownsMidiOutputChannel::getEffectLevel(uint8 type) {
uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan);
if (type == 28)
@@ -411,45 +411,45 @@ int16 TownsMidiOutputChannel::getEffectState(uint8 type) {
type -= 13;
int32 res = 0;
- uint8 cs = (_driver->_chanState[chan].get(_effectDefs[type * 4] >> 5) & _effectDefs[type * 4 + 2]) >> _effectDefs[type * 4 + 1];
- if (_effectDefs[type * 4 + 3])
- res = _effectDefs[type * 4 + 3] - cs;
+ uint8 cs = (_driver->_chanState[chan].get(_effectDefaults[type * 4] >> 5) & _effectDefaults[type * 4 + 2]) >> _effectDefaults[type * 4 + 1];
+ if (_effectDefaults[type * 4 + 3])
+ res = _effectDefaults[type * 4 + 3] - cs;
return res;
}
-void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) {
- a->numLoop = 1;
- a->fld_1 = 0;
- a->modWheelLast = 31;
- a->duration = effectData[0] * 63;
- a->ar1[0] = effectData[1];
- a->ar1[1] = effectData[3];
- a->ar1[2] = effectData[5];
- a->ar1[3] = effectData[6];
- a->ar2[0] = effectData[2];
- a->ar2[1] = effectData[4];
- a->ar2[2] = 0;
- a->ar2[3] = effectData[7];
- updateEffect(a);
+void TownsMidiOutputChannel::initEffect(EffectState *s, const uint8 *effectData) {
+ s->envState = 1;
+ s->envStepLen = 0;
+ s->modWheelLast = 31;
+ s->duration = effectData[0] * 63;
+ s->envStepping[0] = effectData[1];
+ s->envStepping[1] = effectData[3];
+ s->envStepping[2] = effectData[5];
+ s->envStepping[3] = effectData[6];
+ s->envMod[0] = effectData[2];
+ s->envMod[1] = effectData[4];
+ s->envMod[2] = 0;
+ s->envMod[3] = effectData[7];
+ updateEffect(s);
}
-void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) {
- uint8 f = updateEffectOuter(a, b);
+void TownsMidiOutputChannel::updateEffectGenerator(EffectState *s, EffectDef *d) {
+ uint8 f = updateEffectEnvelope(s, d);
if (f & 1) {
- switch (b->type) {
+ switch (d->type) {
case 0:
- _carrierTl = a->effectState + b->inc; /*???*/
+ _operator2Tl = s->currentLevel + d->phase;
break;
case 13:
- _modulatorTl = a->effectState + b->inc; /*???*/
+ _operator1Tl = s->currentLevel + d->phase;
break;
case 30:
- b->a->modWheelState = b->inc;
+ d->s->modWheelState = d->phase;
break;
case 31:
- b->a->modWheelSensitivity = b->inc;
+ d->s->modWheelSensitivity = d->phase;
break;
default:
break;
@@ -457,60 +457,60 @@ void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) {
}
if (f & 2) {
- if (b->fld_6)
+ if (d->loopRefresh)
keyOn();
}
}
-int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
- if (a->duration) {
- a->duration -= 17;
- if (a->duration <= 0) {
- a->numLoop = 0;
+int TownsMidiOutputChannel::updateEffectEnvelope(EffectState *s, EffectDef *d) {
+ if (s->duration) {
+ s->duration -= 17;
+ if (s->duration <= 0) {
+ s->envState = 0;
return 0;
}
}
- int32 t = a->fld_1 + a->fld_25;
+ int32 t = s->envStepLen + s->envChangePerStep;
- a->fld_2e += a->fld_2a;
- if (a->fld_2e >= a->fld_1d) {
- a->fld_2e -= a->fld_1d;
- t += a->dir;
+ s->envChangeCountRem += s->envChangePerStepRem;
+ if (s->envChangeCountRem >= s->envStateNumSteps) {
+ s->envChangeCountRem -= s->envStateNumSteps;
+ t += s->dir;
}
int retFlags = 0;
- if (t != a->fld_1 || a->modWheelState != a->modWheelLast) {
- a->fld_1 = t;
- a->modWheelLast = a->modWheelState;
- t = lookupVolume(t, a->modWheelState);
- if (t != b->inc)
- b->inc = t;
+ if (t != s->envStepLen || (s->modWheelState != s->modWheelLast)) {
+ s->envStepLen = t;
+ s->modWheelLast = s->modWheelState;
+ t = calcModWheelLevel(t, s->modWheelState);
+ if (t != d->phase)
+ d->phase = t;
retFlags |= 1;
}
- if (--a->fld_21)
+ if (--s->envStateStepCounter)
return retFlags;
- if (++a->numLoop > 4) {
- if (!a->fld_11) {
- a->numLoop = 0;
+ if (++s->envState > 4) {
+ if (!s->loop) {
+ s->envState = 0;
return retFlags;
}
- a->numLoop = 1;
+ s->envState = 1;
retFlags |= 2;
}
- updateEffect(a);
+ updateEffect(s);
return retFlags;
}
-void TownsMidiOutputChannel::updateEffect(StateA *a) {
- uint8 c = a->numLoop - 1;
- uint8 v = a->ar1[c];
- int32 e = _effectData[_driver->_chanEffectLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]];
+void TownsMidiOutputChannel::updateEffect(EffectState *s) {
+ uint8 st= s->envState - 1;
+ uint8 v = s->envStepping[st];
+ int32 e = _effectEnvStepTable[_driver->_chanEffectLevelModifier[((v & 0x7f) << 5) + s->modWheelSensitivity]];
if (v & 0x80)
e = _driver->randomValue(e);
@@ -518,58 +518,59 @@ void TownsMidiOutputChannel::updateEffect(StateA *a) {
if (!e)
e = 1;
- a->fld_1d = a->fld_21 = e;
+ s->envStateNumSteps = s->envStateStepCounter = e;
int32 d = 0;
- if (c != 2) {
- v = a->ar2[c];
- e = lookupVolume(a->fld_9, (v & 0x7f) - 31);
+ if (st != 2) {
+ v = s->envMod[st];
+ e = calcModWheelLevel(s->envTargetLevel, (v & 0x7f) - 31);
if (v & 0x80)
e = _driver->randomValue(e);
- if (e + a->effectState > a->fld_9) {
- e = a->fld_9 - a->effectState;
+ if (e + s->currentLevel > s->envTargetLevel) {
+ e = s->envTargetLevel - s->currentLevel;
} else {
- if (e + a->effectState + 1 <= 0)
- e = -a->effectState;
+ if (e + s->currentLevel + 1 <= 0)
+ e = -s->currentLevel;
}
- d = e - a->fld_1;
+ d = e - s->envStepLen;
}
- a->fld_25 = d / a->fld_1d;
- a->dir = (d < 0) ? -1 : 1;
- d *= a->dir;
- a->fld_2a = d % a->fld_1d;
- a->fld_2e = 0;
+ s->envChangePerStep = d / s->envStateNumSteps;
+ s->dir = (d < 0) ? -1 : 1;
+ d *= s->dir;
+ s->envChangePerStepRem = d % s->envStateNumSteps;
+ s->envChangeCountRem = 0;
}
-int TownsMidiOutputChannel::lookupVolume(int a, int b) {
- if (b == 0)
+int TownsMidiOutputChannel::calcModWheelLevel(int lvl, int mod) {
+ if (mod == 0)
return 0;
- if (b == 31)
- return a;
+ if (mod == 31)
+ return lvl;
- if (a > 63 || a < -63)
- return ((a + 1) * b) >> 5;
+ if (lvl > 63 || lvl < -63)
+ return ((lvl + 1) * mod) >> 5;
- if (b < 0) {
- if (a < 0)
- return _driver->_chanEffectLevel[((-a) << 5) - b];
+ if (mod < 0) {
+ if (mod < 0)
+ return _driver->_chanEffectLevelModifier[((-lvl) << 5) - mod];
else
- return -_driver->_chanEffectLevel[(a << 5) - b];
+ return -_driver->_chanEffectLevelModifier[(lvl << 5) - mod];
} else {
- if (a < 0)
- return -_driver->_chanEffectLevel[((-a) << 5) + b];
+ if (mod < 0)
+ return -_driver->_chanEffectLevelModifier[((-lvl) << 5) + mod];
else
- return _driver->_chanEffectLevel[((-a) << 5) + b];
+ return _driver->_chanEffectLevelModifier[((-lvl) << 5) + mod];
}
+
+ return 0;
}
void TownsMidiOutputChannel::keyOn() {
- // This driver uses only 2 operators since it is just a modified AdLib driver.
out(0x28, 0x30);
}
@@ -578,12 +579,11 @@ void TownsMidiOutputChannel::keyOff() {
}
void TownsMidiOutputChannel::keyOnSetFreq(uint16 frq) {
- uint8 t = (frq << 1) >> 8;
- frq = (_freqMSB[t] << 11) | _freqLSB[t] ;
+ uint16 note = (frq << 1) >> 8;
+ frq = (_freqMSB[note] << 11) | _freqLSB[note] ;
out(0xa4, frq >> 8);
out(0xa0, frq & 0xff);
- out(0x28, 0);
- // This driver uses only 2 operators since it is just a modified AdLib driver.
+ //out(0x28, 0x00);
out(0x28, 0x30);
}
@@ -607,7 +607,7 @@ const uint8 TownsMidiOutputChannel::_chanMap2[] = {
3, 4, 5, 11, 12, 13
};
-const uint8 TownsMidiOutputChannel::_effectDefs[] = {
+const uint8 TownsMidiOutputChannel::_effectDefaults[] = {
0x40, 0x00, 0x3F, 0x3F, 0xE0, 0x02, 0x00, 0x00, 0x40, 0x06, 0xC0, 0x00,
0x20, 0x00, 0x0F, 0x00, 0x60, 0x04, 0xF0, 0x0F, 0x60, 0x00, 0x0F, 0x0F,
0x80, 0x04, 0xF0, 0x0F, 0x80, 0x00, 0x0F, 0x0F, 0xE0, 0x00, 0x03, 0x00,
@@ -615,7 +615,7 @@ const uint8 TownsMidiOutputChannel::_effectDefs[] = {
0x20, 0x04, 0x10, 0x00, 0xC0, 0x00, 0x01, 0x00, 0xC0, 0x01, 0x0E, 0x00
};
-const uint16 TownsMidiOutputChannel::_effectData[] = {
+const uint16 TownsMidiOutputChannel::_effectEnvStepTable[] = {
0x0001, 0x0002, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
0x000A, 0x000C, 0x000E, 0x0010, 0x0012, 0x0015, 0x0018, 0x001E,
0x0024, 0x0032, 0x0040, 0x0052, 0x0064, 0x0088, 0x00A0, 0x00C0,
@@ -714,26 +714,26 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
oc->_sustainNoteOff = 0;
oc->_duration = _instrument[29] * 63;
- oc->_modulatorTl = (_instrument[1] & 0x3f) + _driver->_chanEffectLevel[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
- if (oc->_modulatorTl > 63)
- oc->_modulatorTl = 63;
+ oc->_operator1Tl = (_instrument[1] & 0x3f) + _driver->_chanEffectLevelModifier[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
+ if (oc->_operator1Tl > 63)
+ oc->_operator1Tl = 63;
- oc->_carrierTl = (_instrument[6] & 0x3f) + _driver->_chanEffectLevel[((velocity >> 1) << 5) + (_instrument[9] >> 2)];
- if (oc->_carrierTl > 63)
- oc->_carrierTl = 63;
+ oc->_operator2Tl = (_instrument[6] & 0x3f) + _driver->_chanEffectLevelModifier[((velocity >> 1) << 5) + (_instrument[9] >> 2)];
+ if (oc->_operator2Tl > 63)
+ oc->_operator2Tl = 63;
- oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_modulatorTl << 5)]] : oc->_modulatorTl, _programAdjustLevel[_driver->_chanEffectLevel[(_tl >> 2) + (oc->_carrierTl << 5)]]);
+ oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_chanEffectLevelModifier[(_tl >> 2) + (oc->_operator1Tl << 5)]] : oc->_operator1Tl, _programAdjustLevel[_driver->_chanEffectLevelModifier[(_tl >> 2) + (oc->_operator2Tl << 5)]]);
oc->noteOn(note + _transpose, _freqLSB);
if (_instrument[11] & 0x80)
oc->setupEffects(0, _instrument[11], &_instrument[12]);
else
- oc->_stateA[0].numLoop = 0;
+ oc->_effectStates[0].envState = 0;
if (_instrument[20] & 0x80)
oc->setupEffects(1, _instrument[20], &_instrument[21]);
else
- oc->_stateA[1].numLoop = 0;
+ oc->_effectStates[1].envState = 0;
}
void TownsMidiInputChannel::programChange(byte program) {
@@ -795,7 +795,6 @@ void TownsMidiInputChannel::controlModulationWheel(byte value) {
void TownsMidiInputChannel::controlVolume(byte value) {
/* This is all done inside the imuse code
-
uint16 v1 = _ctrlVolume + 1;
uint16 v2 = value;
if (_chanIndex != 16) {
@@ -805,10 +804,6 @@ void TownsMidiInputChannel::controlVolume(byte value) {
_tl = (v1 * v2) >> 7;*/
_tl = value;
-
- /* nullsub
- _out->setVolume(_tl);
- */
}
void TownsMidiInputChannel::controlPanPos(byte value) {
@@ -865,13 +860,13 @@ int MidiDriver_TOWNS::open() {
_chanState = new TownsMidiChanState[32];
- _chanEffectLevel = new uint8[2048];
+ _chanEffectLevelModifier = new uint8[2048];
for (int i = 0; i < 64; i++) {
for (int ii = 0; ii < 32; ii++)
- _chanEffectLevel[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff;
+ _chanEffectLevelModifier[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff;
}
for (int i = 0; i < 64; i++)
- _chanEffectLevel[i << 5] = 0;
+ _chanEffectLevelModifier[i << 5] = 0;
_intf->callback(0);
@@ -916,8 +911,8 @@ void MidiDriver_TOWNS::close() {
delete[] _chanState;
_chanState = 0;
- delete[] _chanEffectLevel;
- _chanEffectLevel = 0;
+ delete[] _chanEffectLevelModifier;
+ _chanEffectLevelModifier = 0;
}
void MidiDriver_TOWNS::send(uint32 b) {
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index 8dc71f3..52298d7 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -78,7 +78,7 @@ private:
bool _open;
- uint8 *_chanEffectLevel;
+ uint8 *_chanEffectLevelModifier;
};
#endif
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
index 263986e..09d3ca3 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -39,45 +39,22 @@ public:
void recalculateRates();
void generateOutput(int32 phasebuf, int32 *feedbuf, int32 &out);
- void feedbackLevel(int32 level) {
- _feedbackLevel = level ? level + 6 : 0;
- }
- void detune(int value) {
- _detn = &_detnTbl[value << 5];
- }
- void multiple(uint32 value) {
- _multiple = value ? (value << 1) : 1;
- }
- void attackRate(uint32 value) {
- _specifiedAttackRate = value;
- }
+ void feedbackLevel(int32 level);
+ void detune(int value);
+ void multiple(uint32 value);
+ void attackRate(uint32 value);
bool scaleRate(uint8 value);
- void decayRate(uint32 value) {
- _specifiedDecayRate = value;
- recalculateRates();
- }
- void sustainRate(uint32 value) {
- _specifiedSustainRate = value;
- recalculateRates();
- }
- void sustainLevel(uint32 value) {
- _sustainLevel = (value == 0x0f) ? 0x3e0 : value << 5;
- }
- void releaseRate(uint32 value) {
- _specifiedReleaseRate = value;
- recalculateRates();
- }
- void totalLevel(uint32 value) {
- _totalLevel = value << 3;
- }
- void ampModulation(bool enable) {
- _ampMod = enable;
- }
+ void decayRate(uint32 value);
+ void sustainRate(uint32 value);
+ void sustainLevel(uint32 value);
+ void releaseRate(uint32 value);
+ void totalLevel(uint32 value);
+ void ampModulation(bool enable);
void reset();
protected:
EnvelopeState _state;
- bool _playing;
+ bool _holdKey;
uint32 _feedbackLevel;
uint32 _multiple;
uint32 _totalLevel;
@@ -122,7 +99,7 @@ TownsPC98_FmSynthOperator::TownsPC98_FmSynthOperator(const uint32 timerbase, con
_rtt(rtt), _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable),
_sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(timerbase * 2),
_specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0),
- _phase(0), _state(kEnvReady), _playing(false), _timer(0), _keyScale1(0),
+ _phase(0), _state(kEnvReady), _holdKey(false), _timer(0), _keyScale1(0),
_keyScale2(0), _currentLevel(1023), _ampMod(false), _tickCount(0) {
fs_a.rate = fs_a.shift = fs_d.rate = fs_d.shift = fs_s.rate = fs_s.shift = fs_r.rate = fs_r.shift = 0;
@@ -131,19 +108,19 @@ TownsPC98_FmSynthOperator::TownsPC98_FmSynthOperator(const uint32 timerbase, con
}
void TownsPC98_FmSynthOperator::keyOn() {
- if (_playing)
+ if (_holdKey)
return;
- _playing = true;
+ _holdKey = true;
_state = kEnvAttacking;
_phase = 0;
}
void TownsPC98_FmSynthOperator::keyOff() {
- if (!_playing)
+ if (!_holdKey)
return;
- _playing = false;
+ _holdKey = false;
if (_state != kEnvReady)
_state = kEnvReleasing;
}
@@ -199,39 +176,42 @@ void TownsPC98_FmSynthOperator::generateOutput(int32 phasebuf, int32 *feed, int3
int32 targetLevel = 0;
EnvelopeState nextState = kEnvReady;
- switch (_state) {
- case kEnvReady:
- return;
- case kEnvAttacking:
- targetLevel = 0;
- nextState = kEnvDecaying;
- if ((_specifiedAttackRate << 1) + _keyScale2 < 64) {
- targetTime = (1 << fs_a.shift) - 1;
- levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4;
+ for (bool loop = true; loop;) {
+ switch (_state) {
+ case kEnvReady:
+ return;
+ case kEnvAttacking:
+ targetLevel = 0;
+ nextState = _sustainLevel ? kEnvDecaying : kEnvSustaining;
+ if ((_specifiedAttackRate << 1) + _keyScale2 < 62) {
+ targetTime = (1 << fs_a.shift) - 1;
+ levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4;
+ } else {
+ _currentLevel = targetLevel;
+ _state = nextState;
+ continue;
+ }
+ break;
+ case kEnvDecaying:
+ targetTime = (1 << fs_d.shift) - 1;
+ nextState = kEnvSustaining;
+ targetLevel = _sustainLevel;
+ levelIncrement = _adTbl[fs_d.rate + ((_tickCount >> fs_d.shift) & 7)];
+ break;
+ case kEnvSustaining:
+ targetTime = (1 << fs_s.shift) - 1;
+ nextState = kEnvSustaining;
+ targetLevel = 1023;
+ levelIncrement = _adTbl[fs_s.rate + ((_tickCount >> fs_s.shift) & 7)];
+ break;
+ case kEnvReleasing:
+ targetTime = (1 << fs_r.shift) - 1;
+ nextState = kEnvReady;
+ targetLevel = 1023;
+ levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)];
break;
- } else {
- _currentLevel = targetLevel;
- _state = nextState;
}
- // Fall through
- case kEnvDecaying:
- targetTime = (1 << fs_d.shift) - 1;
- nextState = kEnvSustaining;
- targetLevel = _sustainLevel;
- levelIncrement = _adTbl[fs_d.rate + ((_tickCount >> fs_d.shift) & 7)];
- break;
- case kEnvSustaining:
- targetTime = (1 << fs_s.shift) - 1;
- nextState = kEnvSustaining;
- targetLevel = 1023;
- levelIncrement = _adTbl[fs_s.rate + ((_tickCount >> fs_s.shift) & 7)];
- break;
- case kEnvReleasing:
- targetTime = (1 << fs_r.shift) - 1;
- nextState = kEnvReady;
- targetLevel = 1023;
- levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)];
- break;
+ loop = false;
}
if (!(_tickCount & targetTime)) {
@@ -272,6 +252,63 @@ void TownsPC98_FmSynthOperator::generateOutput(int32 phasebuf, int32 *feed, int3
out += *o;
}
+void TownsPC98_FmSynthOperator::feedbackLevel(int32 level) {
+ _feedbackLevel = level ? level + 6 : 0;
+}
+
+void TownsPC98_FmSynthOperator::detune(int value) {
+ _detn = &_detnTbl[value << 5];
+}
+
+void TownsPC98_FmSynthOperator::multiple(uint32 value) {
+ _multiple = value ? (value << 1) : 1;
+}
+
+void TownsPC98_FmSynthOperator::attackRate(uint32 value) {
+ _specifiedAttackRate = value;
+}
+
+bool TownsPC98_FmSynthOperator::scaleRate(uint8 value) {
+ value = 3 - value;
+ if (_keyScale1 != value) {
+ _keyScale1 = value;
+ return true;
+ }
+
+ int k = _keyScale2;
+ int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0;
+ fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136;
+ fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0;
+ return false;
+}
+
+void TownsPC98_FmSynthOperator::decayRate(uint32 value) {
+ _specifiedDecayRate = value;
+ recalculateRates();
+}
+
+void TownsPC98_FmSynthOperator::sustainRate(uint32 value) {
+ _specifiedSustainRate = value;
+ recalculateRates();
+ }
+
+void TownsPC98_FmSynthOperator::sustainLevel(uint32 value) {
+ _sustainLevel = (value == 0x0f) ? 0x3e0 : value << 5;
+}
+
+void TownsPC98_FmSynthOperator::releaseRate(uint32 value) {
+ _specifiedReleaseRate = value;
+ recalculateRates();
+}
+
+void TownsPC98_FmSynthOperator::totalLevel(uint32 value) {
+ _totalLevel = value << 3;
+}
+
+void TownsPC98_FmSynthOperator::ampModulation(bool enable) {
+ _ampMod = enable;
+}
+
void TownsPC98_FmSynthOperator::reset() {
keyOff();
_timer = 0;
@@ -292,20 +329,6 @@ void TownsPC98_FmSynthOperator::reset() {
ampModulation(false);
}
-bool TownsPC98_FmSynthOperator::scaleRate(uint8 value) {
- value = 3 - value;
- if (_keyScale1 != value) {
- _keyScale1 = value;
- return true;
- }
-
- int k = _keyScale2;
- int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0;
- fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136;
- fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0;
- return false;
-}
-
class TownsPC98_FmSynthSquareSineSource {
public:
TownsPC98_FmSynthSquareSineSource(const uint32 timerbase, const uint32 rtt);
Commit: a9f7888ad993e292e43f7f4f25ae8fb086099372
https://github.com/scummvm/scummvm/commit/a9f7888ad993e292e43f7f4f25ae8fb086099372
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:45-07:00
Commit Message:
FM TOWNS AUDIO: some fixes and renaming
- renamed some stuff in the new midi driver code
- fixed minor bug in midi driver code
- fixed minor bug in euphony driver code
- add some functionality to towns audio interface
Changed paths:
audio/softsynth/fmtowns_pc98/towns_audio.cpp
audio/softsynth/fmtowns_pc98/towns_euphony.cpp
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_midi.h
audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
index 6679e65..f2d249b 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -163,9 +163,10 @@ private:
int intf_fmReset(va_list &args);
int intf_setOutputVolume(va_list &args);
int intf_resetOutputVolume(va_list &args);
+ int intf_getOutputVolume(va_list &args);
int intf_setOutputMute(va_list &args);
int intf_cdaToggle(va_list &args);
- int intf_getOutputVolume(va_list &args);
+ int intf_getOutputVolume2(va_list &args);
int intf_getOutputMute(va_list &args);
int intf_pcmUpdateEnvelopeGenerator(va_list &args);
@@ -224,7 +225,7 @@ private:
void updateOutputVolume();
uint8 _outputVolumeFlags;
uint8 _outputLevel[16];
- uint8 _outputMuteFlags;
+ uint8 _outputMute[16];
const float _baserate;
uint32 _timerBase;
@@ -253,7 +254,7 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA
_fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0),
_baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver),
_pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume),
- _outputVolumeFlags(0), _outputMuteFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0),
+ _outputVolumeFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0),
_pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _ready(false) {
#define INTCB(x) &TownsAudioInterfaceIntern::intf_##x
@@ -345,13 +346,13 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA
INTCB(setOutputVolume),
// 68
INTCB(resetOutputVolume),
- INTCB(notImpl),
+ INTCB(getOutputVolume),
INTCB(setOutputMute),
INTCB(notImpl),
// 72
INTCB(notImpl),
INTCB(cdaToggle),
- INTCB(getOutputVolume),
+ INTCB(getOutputVolume2),
INTCB(getOutputMute),
// 76
INTCB(notImpl),
@@ -368,6 +369,7 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA
memset(_fmSaveReg, 0, sizeof(_fmSaveReg));
memset(_outputLevel, 0, sizeof(_outputLevel));
+ memset(_outputMute, 0, sizeof(_outputMute));
_timerBase = (uint32)(_baserate * 1000000.0f);
_tickLength = 2 * _timerBase;
@@ -929,11 +931,13 @@ int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) {
if (chanType > 1) {
_outputLevel[chan + chanType] = left;
+ _outputMute[chan + chanType] = 0;
} else {
if (chanType == 0)
chan -= 8;
_outputLevel[chan] = left;
_outputLevel[chan + 1] = right;
+ _outputMute[chan] = _outputMute[chan + 1] = 0;
}
updateOutputVolume();
@@ -943,15 +947,56 @@ int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) {
int TownsAudioInterfaceIntern::intf_resetOutputVolume(va_list &args) {
memset(_outputLevel, 0, sizeof(_outputLevel));
- _outputMuteFlags = 0;
_outputVolumeFlags = 0;
updateOutputVolume();
return 0;
}
+int TownsAudioInterfaceIntern::intf_getOutputVolume(va_list &args) {
+ int chanType = va_arg(args, int);
+ int *left = va_arg(args, int*);
+ int *right = va_arg(args, int*);
+
+ uint8 chan = (chanType & 0x40) ? 8 : 12;
+ chanType &= 3;
+
+ if (chanType > 1) {
+ *left = _outputLevel[chan + chanType] & 0x3f;
+ } else {
+ if (chanType == 0)
+ chan -= 8;
+ *left = _outputLevel[chan] & 0x3f;
+ *right = _outputLevel[chan + 1] & 0x3f;
+ }
+
+ return 0;
+}
+
int TownsAudioInterfaceIntern::intf_setOutputMute(va_list &args) {
int flags = va_arg(args, int);
- _outputMuteFlags = flags & 3;
+ _outputVolumeFlags = flags;
+ uint8 mute = flags & 3;
+ uint8 f = flags & 0xff;
+
+ memset(_outputMute, 1, 8);
+ if (mute & 2)
+ memset(_outputMute + 12, 1, 4);
+ if (mute & 1)
+ memset(_outputMute + 8, 1, 4);
+
+ _outputMute[(f < 0x80) ? 11 : 15] = 0;
+ f += f;
+ _outputMute[(f < 0x80) ? 10 : 14] = 0;
+ f += f;
+ _outputMute[(f < 0x80) ? 8 : 12] = 0;
+ f += f;
+ _outputMute[(f < 0x80) ? 9 : 13] = 0;
+ f += f;
+ _outputMute[(f < 0x80) ? 0 : 4] = 0;
+ f += f;
+ _outputMute[(f < 0x80) ? 1 : 5] = 0;
+ f += f;
+
updateOutputVolume();
return 0;
}
@@ -962,7 +1007,7 @@ int TownsAudioInterfaceIntern::intf_cdaToggle(va_list &args) {
return 0;
}
-int TownsAudioInterfaceIntern::intf_getOutputVolume (va_list &args) {
+int TownsAudioInterfaceIntern::intf_getOutputVolume2(va_list &args) {
return 0;
}
@@ -1602,10 +1647,10 @@ void TownsAudioInterfaceIntern::updateOutputVolume() {
// balance values for our -128 to 127 volume range
// CD-AUDIO
- uint32 maxVol = MAX(_outputLevel[12], _outputLevel[13]);
+ uint32 maxVol = MAX(_outputLevel[12] * (_outputMute[12] ^ 1), _outputLevel[13] * (_outputMute[13] ^ 1));
int volume = (int)(((float)(maxVol * 255) / 63.0f));
- int balance = maxVol ? (int)( ( ((int)_outputLevel[13] - _outputLevel[12]) * 127) / (float)maxVol) : 0;
+ int balance = maxVol ? (int)( ( ((int)_outputLevel[13] * (_outputMute[13] ^ 1) - _outputLevel[12] * (_outputMute[12] ^ 1)) * 127) / (float)maxVol) : 0;
g_system->getAudioCDManager()->setVolume(volume);
g_system->getAudioCDManager()->setBalance(balance);
diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
index f161228..f7aa33f 100644
--- a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
@@ -81,7 +81,7 @@ void TownsEuphonyDriver::reset() {
_intf->callback(0);
_intf->callback(74);
- _intf->callback(70);
+ _intf->callback(70, 0);
_intf->callback(75, 3);
setTimerA(true, 1);
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index f467952..5e7d750 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -23,9 +23,12 @@
*/
#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
+#include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
#include "common/textconsole.h"
#include "common/system.h"
+enum EnvelopeState;
+
class TownsMidiOutputChannel {
friend class TownsMidiInputChannel;
public:
@@ -51,40 +54,40 @@ public:
int checkPriority(int pri);
private:
- struct EffectState {
- uint8 envState;
- int32 envStepLen;
- int32 duration;
- int32 envTargetLevel;
+ struct EffectEnvelope {
+ uint8 state;
int32 currentLevel;
+ int32 duration;
+ int32 maxLevel;
+ int32 startLevel;
uint8 loop;
- uint8 envStepping[4];
- uint8 envMod[4];
+ uint8 stateTargetLevels[4];
+ uint8 stateModWheelLevels[4];
int8 modWheelSensitivity;
int8 modWheelState;
int8 modWheelLast;
- uint16 envStateNumSteps;
- uint32 envStateStepCounter;
- int32 envChangePerStep;
+ uint16 numSteps;
+ uint32 stepCounter;
+ int32 incrPerStep;
int8 dir;
- uint32 envChangePerStepRem;
- uint32 envChangeCountRem;
- } *_effectStates;
+ uint32 incrPerStepRem;
+ uint32 incrCountRem;
+ } *_effectEnvelopes;
struct EffectDef {
int32 phase;
uint8 type;
uint8 useModWheel;
uint8 loopRefresh;
- EffectState *s;
+ EffectEnvelope *s;
} *_effectDefs;
- int16 getEffectLevel(uint8 type);
- void initEffect(EffectState *s, const uint8 *effectData);
- void updateEffectGenerator(EffectState *s, EffectDef *d);
- int updateEffectEnvelope(EffectState *s, EffectDef *d);
- void updateEffect(EffectState *s);
- int calcModWheelLevel(int lvl, int mod);
+ void startEffect(EffectEnvelope *s, const uint8 *effectData);
+ void updateEffectGenerator(EffectEnvelope *s, EffectDef *d);
+ int advanceEffectEnvelope(EffectEnvelope *s, EffectDef *d);
+ void initNextEnvelopeState(EffectEnvelope *s);
+ int16 getEffectStartLevel(uint8 type);
+ int getEffectModLevel(int lvl, int mod);
void keyOn();
void keyOff();
@@ -216,17 +219,17 @@ uint8 TownsMidiChanState::get(uint8 type) {
TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex),
_in(0), _prev(0), _next(0), _adjustModTl(0), _operator2Tl(0), _note(0), _operator1Tl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) {
- _effectStates = new EffectState[2];
+ _effectEnvelopes = new EffectEnvelope[2];
_effectDefs = new EffectDef[2];
- memset(_effectStates, 0, 2 * sizeof(EffectState));
+ memset(_effectEnvelopes, 0, 2 * sizeof(EffectEnvelope));
memset(_effectDefs, 0, 2 * sizeof(EffectDef));
- _effectDefs[0].s = &_effectStates[1];
- _effectDefs[1].s = &_effectStates[0];
+ _effectDefs[0].s = &_effectEnvelopes[1];
+ _effectDefs[1].s = &_effectEnvelopes[0];
}
TownsMidiOutputChannel::~TownsMidiOutputChannel() {
- delete[] _effectStates;
+ delete[] _effectEnvelopes;
delete[] _effectDefs;
}
@@ -295,10 +298,10 @@ void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, u
}
void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *effectData) {
- uint16 effectTargetLevel[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F };
+ uint16 effectMaxLevel[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F };
uint8 effectType[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 };
- EffectState *s = &_effectStates[index];
+ EffectEnvelope *s = &_effectEnvelopes[index];
EffectDef *d = &_effectDefs[index];
d->phase = 0;
@@ -306,39 +309,39 @@ void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *e
s->loop = flags & 0x20;
d->loopRefresh = flags & 0x10;
d->type = effectType[flags & 0x0f];
- s->envTargetLevel = effectTargetLevel[flags & 0x0f];
+ s->maxLevel = effectMaxLevel[flags & 0x0f];
s->modWheelSensitivity = 31;
s->modWheelState = d->useModWheel ? _in->_modWheel >> 2 : 31;
switch (d->type) {
case 0:
- s->currentLevel = _operator2Tl;
+ s->startLevel = _operator2Tl;
break;
case 13:
- s->currentLevel = _operator1Tl;
+ s->startLevel = _operator1Tl;
break;
case 30:
- s->currentLevel = 31;
+ s->startLevel = 31;
d->s->modWheelState = 0;
break;
case 31:
- s->currentLevel = 0;
+ s->startLevel = 0;
d->s->modWheelSensitivity = 0;
break;
default:
- s->currentLevel = getEffectLevel(d->type);
+ s->startLevel = getEffectStartLevel(d->type);
break;
}
- initEffect(s, effectData);
+ startEffect(s, effectData);
}
void TownsMidiOutputChannel::setModWheel(uint8 value) {
- if (_effectStates[0].envState && _effectDefs[0].type)
- _effectStates[0].modWheelState = value >> 2;
+ if (_effectEnvelopes[0].state != kEnvReady && _effectDefs[0].type)
+ _effectEnvelopes[0].modWheelState = value >> 2;
- if (_effectStates[1].envState && _effectDefs[1].type)
- _effectStates[1].modWheelState = value >> 2;
+ if (_effectEnvelopes[1].state != kEnvReady && _effectDefs[1].type)
+ _effectEnvelopes[1].modWheelState = value >> 2;
}
void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) {
@@ -381,8 +384,8 @@ bool TownsMidiOutputChannel::update() {
}
for (int i = 0; i < 2; i++) {
- if (_effectStates[i].envState)
- updateEffectGenerator(&_effectStates[i], &_effectDefs[i]);
+ if (_effectEnvelopes[i].state != kEnvReady)
+ updateEffectGenerator(&_effectEnvelopes[i], &_effectDefs[i]);
}
return false;
@@ -398,52 +401,32 @@ int TownsMidiOutputChannel::checkPriority(int pri) {
return kHighPriority;
}
-int16 TownsMidiOutputChannel::getEffectLevel(uint8 type) {
- uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan);
-
- if (type == 28)
- return 15;
- else if (type == 29)
- return 383;
- else if (type > 29)
- return 0;
- else if (type > 12)
- type -= 13;
-
- int32 res = 0;
- uint8 cs = (_driver->_chanState[chan].get(_effectDefaults[type * 4] >> 5) & _effectDefaults[type * 4 + 2]) >> _effectDefaults[type * 4 + 1];
- if (_effectDefaults[type * 4 + 3])
- res = _effectDefaults[type * 4 + 3] - cs;
-
- return res;
-}
-
-void TownsMidiOutputChannel::initEffect(EffectState *s, const uint8 *effectData) {
- s->envState = 1;
- s->envStepLen = 0;
+void TownsMidiOutputChannel::startEffect(EffectEnvelope *s, const uint8 *effectData) {
+ s->state = kEnvAttacking;
+ s->currentLevel = 0;
s->modWheelLast = 31;
s->duration = effectData[0] * 63;
- s->envStepping[0] = effectData[1];
- s->envStepping[1] = effectData[3];
- s->envStepping[2] = effectData[5];
- s->envStepping[3] = effectData[6];
- s->envMod[0] = effectData[2];
- s->envMod[1] = effectData[4];
- s->envMod[2] = 0;
- s->envMod[3] = effectData[7];
- updateEffect(s);
+ s->stateTargetLevels[0] = effectData[1];
+ s->stateTargetLevels[1] = effectData[3];
+ s->stateTargetLevels[2] = effectData[5];
+ s->stateTargetLevels[3] = effectData[6];
+ s->stateModWheelLevels[0] = effectData[2];
+ s->stateModWheelLevels[1] = effectData[4];
+ s->stateModWheelLevels[2] = 0;
+ s->stateModWheelLevels[3] = effectData[7];
+ initNextEnvelopeState(s);
}
-void TownsMidiOutputChannel::updateEffectGenerator(EffectState *s, EffectDef *d) {
- uint8 f = updateEffectEnvelope(s, d);
+void TownsMidiOutputChannel::updateEffectGenerator(EffectEnvelope *s, EffectDef *d) {
+ uint8 f = advanceEffectEnvelope(s, d);
if (f & 1) {
switch (d->type) {
case 0:
- _operator2Tl = s->currentLevel + d->phase;
+ _operator2Tl = s->startLevel + d->phase;
break;
case 13:
- _operator1Tl = s->currentLevel + d->phase;
+ _operator1Tl = s->startLevel + d->phase;
break;
case 30:
d->s->modWheelState = d->phase;
@@ -462,55 +445,54 @@ void TownsMidiOutputChannel::updateEffectGenerator(EffectState *s, EffectDef *d)
}
}
-int TownsMidiOutputChannel::updateEffectEnvelope(EffectState *s, EffectDef *d) {
+int TownsMidiOutputChannel::advanceEffectEnvelope(EffectEnvelope *s, EffectDef *d) {
if (s->duration) {
s->duration -= 17;
if (s->duration <= 0) {
- s->envState = 0;
+ s->state = kEnvReady;
return 0;
}
}
- int32 t = s->envStepLen + s->envChangePerStep;
+ int32 t = s->currentLevel + s->incrPerStep;
- s->envChangeCountRem += s->envChangePerStepRem;
- if (s->envChangeCountRem >= s->envStateNumSteps) {
- s->envChangeCountRem -= s->envStateNumSteps;
+ s->incrCountRem += s->incrPerStepRem;
+ if (s->incrCountRem >= s->numSteps) {
+ s->incrCountRem -= s->numSteps;
t += s->dir;
}
int retFlags = 0;
- if (t != s->envStepLen || (s->modWheelState != s->modWheelLast)) {
- s->envStepLen = t;
+ if (t != s->currentLevel || (s->modWheelState != s->modWheelLast)) {
+ s->currentLevel = t;
s->modWheelLast = s->modWheelState;
- t = calcModWheelLevel(t, s->modWheelState);
+ t = getEffectModLevel(t, s->modWheelState);
if (t != d->phase)
d->phase = t;
retFlags |= 1;
}
- if (--s->envStateStepCounter)
+ if (--s->stepCounter)
return retFlags;
- if (++s->envState > 4) {
+ if (++s->state > kEnvReleasing) {
if (!s->loop) {
- s->envState = 0;
+ s->state = kEnvReady;
return retFlags;
}
- s->envState = 1;
+ s->state = kEnvAttacking;
retFlags |= 2;
}
- updateEffect(s);
+ initNextEnvelopeState(s);
return retFlags;
}
-void TownsMidiOutputChannel::updateEffect(EffectState *s) {
- uint8 st= s->envState - 1;
- uint8 v = s->envStepping[st];
- int32 e = _effectEnvStepTable[_driver->_chanEffectLevelModifier[((v & 0x7f) << 5) + s->modWheelSensitivity]];
+void TownsMidiOutputChannel::initNextEnvelopeState(EffectEnvelope *s) {
+ uint8 v = s->stateTargetLevels[s->state - 1];
+ int32 e = _effectEnvStepTable[_driver->_operatorLevelTable[((v & 0x7f) << 5) + s->modWheelSensitivity]];
if (v & 0x80)
e = _driver->randomValue(e);
@@ -518,34 +500,54 @@ void TownsMidiOutputChannel::updateEffect(EffectState *s) {
if (!e)
e = 1;
- s->envStateNumSteps = s->envStateStepCounter = e;
+ s->numSteps = s->stepCounter = e;
int32 d = 0;
- if (st != 2) {
- v = s->envMod[st];
- e = calcModWheelLevel(s->envTargetLevel, (v & 0x7f) - 31);
+ if (s->state != kEnvSustaining) {
+ v = s->stateModWheelLevels[s->state - 1];
+ e = getEffectModLevel(s->maxLevel, (v & 0x7f) - 31);
if (v & 0x80)
e = _driver->randomValue(e);
- if (e + s->currentLevel > s->envTargetLevel) {
- e = s->envTargetLevel - s->currentLevel;
+ if (e + s->startLevel > s->maxLevel) {
+ e = s->maxLevel - s->startLevel;
} else {
- if (e + s->currentLevel + 1 <= 0)
- e = -s->currentLevel;
+ if (e + s->startLevel < 0)
+ e = -s->startLevel;
}
- d = e - s->envStepLen;
+ d = e - s->currentLevel;
}
- s->envChangePerStep = d / s->envStateNumSteps;
+ s->incrPerStep = d / s->numSteps;
s->dir = (d < 0) ? -1 : 1;
d *= s->dir;
- s->envChangePerStepRem = d % s->envStateNumSteps;
- s->envChangeCountRem = 0;
+ s->incrPerStepRem = d % s->numSteps;
+ s->incrCountRem = 0;
+}
+
+int16 TownsMidiOutputChannel::getEffectStartLevel(uint8 type) {
+ uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan);
+
+ if (type == 28)
+ return 15;
+ else if (type == 29)
+ return 383;
+ else if (type > 29)
+ return 0;
+ else if (type > 12)
+ type -= 13;
+
+ const uint8 *def = &_effectDefaults[type << 2];
+ uint8 res = (_driver->_chanState[chan].get(def[0] >> 5) & def[2]) >> def[1];
+ if (def[3])
+ res = def[3] - res;
+
+ return res;
}
-int TownsMidiOutputChannel::calcModWheelLevel(int lvl, int mod) {
+int TownsMidiOutputChannel::getEffectModLevel(int lvl, int mod) {
if (mod == 0)
return 0;
@@ -556,15 +558,15 @@ int TownsMidiOutputChannel::calcModWheelLevel(int lvl, int mod) {
return ((lvl + 1) * mod) >> 5;
if (mod < 0) {
- if (mod < 0)
- return _driver->_chanEffectLevelModifier[((-lvl) << 5) - mod];
+ if (lvl < 0)
+ return _driver->_operatorLevelTable[((-lvl) << 5) - mod];
else
- return -_driver->_chanEffectLevelModifier[(lvl << 5) - mod];
+ return -_driver->_operatorLevelTable[(lvl << 5) - mod];
} else {
- if (mod < 0)
- return -_driver->_chanEffectLevelModifier[((-lvl) << 5) + mod];
+ if (lvl < 0)
+ return -_driver->_operatorLevelTable[((-lvl) << 5) + mod];
else
- return _driver->_chanEffectLevelModifier[((-lvl) << 5) + mod];
+ return _driver->_operatorLevelTable[((-lvl) << 5) + mod];
}
return 0;
@@ -714,26 +716,26 @@ void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
oc->_sustainNoteOff = 0;
oc->_duration = _instrument[29] * 63;
- oc->_operator1Tl = (_instrument[1] & 0x3f) + _driver->_chanEffectLevelModifier[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
+ oc->_operator1Tl = (_instrument[1] & 0x3f) + _driver->_operatorLevelTable[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
if (oc->_operator1Tl > 63)
oc->_operator1Tl = 63;
- oc->_operator2Tl = (_instrument[6] & 0x3f) + _driver->_chanEffectLevelModifier[((velocity >> 1) << 5) + (_instrument[9] >> 2)];
+ oc->_operator2Tl = (_instrument[6] & 0x3f) + _driver->_operatorLevelTable[((velocity >> 1) << 5) + (_instrument[9] >> 2)];
if (oc->_operator2Tl > 63)
oc->_operator2Tl = 63;
- oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_chanEffectLevelModifier[(_tl >> 2) + (oc->_operator1Tl << 5)]] : oc->_operator1Tl, _programAdjustLevel[_driver->_chanEffectLevelModifier[(_tl >> 2) + (oc->_operator2Tl << 5)]]);
+ oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_operatorLevelTable[(_tl >> 2) + (oc->_operator1Tl << 5)]] : oc->_operator1Tl, _programAdjustLevel[_driver->_operatorLevelTable[(_tl >> 2) + (oc->_operator2Tl << 5)]]);
oc->noteOn(note + _transpose, _freqLSB);
if (_instrument[11] & 0x80)
oc->setupEffects(0, _instrument[11], &_instrument[12]);
else
- oc->_effectStates[0].envState = 0;
+ oc->_effectEnvelopes[0].state = kEnvReady;
if (_instrument[20] & 0x80)
oc->setupEffects(1, _instrument[20], &_instrument[21]);
else
- oc->_effectStates[1].envState = 0;
+ oc->_effectEnvelopes[1].state = kEnvReady;
}
void TownsMidiInputChannel::programChange(byte program) {
@@ -852,7 +854,7 @@ int MidiDriver_TOWNS::open() {
_channels = new TownsMidiInputChannel*[32];
for (int i = 0; i < 32; i++)
- _channels[i] = new TownsMidiInputChannel(this, i);
+ _channels[i] = new TownsMidiInputChannel(this, i > 8 ? (i + 1) : i);
_out = new TownsMidiOutputChannel*[6];
for (int i = 0; i < 6; i++)
@@ -860,13 +862,13 @@ int MidiDriver_TOWNS::open() {
_chanState = new TownsMidiChanState[32];
- _chanEffectLevelModifier = new uint8[2048];
+ _operatorLevelTable = new uint8[2048];
for (int i = 0; i < 64; i++) {
for (int ii = 0; ii < 32; ii++)
- _chanEffectLevelModifier[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff;
+ _operatorLevelTable[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff;
}
for (int i = 0; i < 64; i++)
- _chanEffectLevelModifier[i << 5] = 0;
+ _operatorLevelTable[i << 5] = 0;
_intf->callback(0);
@@ -911,8 +913,8 @@ void MidiDriver_TOWNS::close() {
delete[] _chanState;
_chanState = 0;
- delete[] _chanEffectLevelModifier;
- _chanEffectLevelModifier = 0;
+ delete[] _operatorLevelTable;
+ _operatorLevelTable = 0;
}
void MidiDriver_TOWNS::send(uint32 b) {
@@ -1009,8 +1011,7 @@ void MidiDriver_TOWNS::updateOutputChannels() {
while (_tickCounter2 >= 16667) {
_tickCounter2 -= 16667;
for (int i = 0; i < 6; i++) {
- TownsMidiOutputChannel *oc = _out[i];
- if (oc->update())
+ if (_out[i]->update())
return;
}
}
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
index 52298d7..2b6e1df 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.h
@@ -78,7 +78,7 @@ private:
bool _open;
- uint8 *_chanEffectLevelModifier;
+ uint8 *_operatorLevelTable;
};
#endif
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
index cbf856c..f7bcc90 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
@@ -44,7 +44,7 @@ class TownsPC98_FmSynthPercussionSource;
#endif
enum EnvelopeState {
- kEnvReady,
+ kEnvReady = 0,
kEnvAttacking,
kEnvDecaying,
kEnvSustaining,
Commit: 747b86433cd7bafb8edacba29776c77653424433
https://github.com/scummvm/scummvm/commit/747b86433cd7bafb8edacba29776c77653424433
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:47-07:00
Commit Message:
SCUMM: partly revert / fix recent detune commit
Changed paths:
engines/scumm/imuse/imuse_internal.h
engines/scumm/imuse/imuse_part.cpp
engines/scumm/imuse/sysex_scumm.cpp
engines/scumm/saveload.h
diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h
index b36bab4..ec60b22 100644
--- a/engines/scumm/imuse/imuse_internal.h
+++ b/engines/scumm/imuse/imuse_internal.h
@@ -302,7 +302,7 @@ struct Part : public Serializable {
byte _pitchbend_factor;
int8 _transpose, _transpose_eff;
byte _vol, _vol_eff;
- int8 _detune, _sysexDetune, _detune_eff;
+ int8 _detune, _detune_eff;
int8 _pan, _pan_eff;
bool _on;
byte _modwheel;
@@ -345,7 +345,6 @@ struct Part : public Serializable {
void set_transpose(int8 transpose);
void set_detune(int8 detune);
- void set_sysexDetune(int8 detune);
void set_pri(int8 pri);
void set_pan(int8 pan);
diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp
index 8815757..808af23 100644
--- a/engines/scumm/imuse/imuse_part.cpp
+++ b/engines/scumm/imuse/imuse_part.cpp
@@ -49,7 +49,6 @@ Part::Part() {
_vol = 0;
_vol_eff = 0;
_detune = 0;
- _sysexDetune = 0;
_detune_eff = 0;
_pan = 0;
_pan_eff = 0;
@@ -73,7 +72,6 @@ void Part::saveLoadWithSerializer(Serializer *ser) {
MKLINE(Part, _transpose, sleInt8, VER(8)),
MKLINE(Part, _vol, sleUint8, VER(8)),
MKLINE(Part, _detune, sleInt8, VER(8)),
- MKLINE(Part, _sysexDetune, sleInt8, VER(85)),
MKLINE(Part, _pan, sleInt8, VER(8)),
MKLINE(Part, _on, sleUint8, VER(8)),
MKLINE(Part, _modwheel, sleUint8, VER(8)),
@@ -112,12 +110,7 @@ void Part::saveLoadWithSerializer(Serializer *ser) {
}
void Part::set_detune(int8 detune) {
- _detune_eff = clamp((_detune = detune) + _player->getDetune() + _sysexDetune, -128, 127);
- sendPitchBend();
-}
-
-void Part::set_sysexDetune(int8 detune) {
- _detune_eff = clamp((_sysexDetune = detune) + _player->getDetune() + _detune, -128, 127);
+ _detune_eff = clamp((_detune = detune) + _player->getDetune(), -128, 127);
sendPitchBend();
}
@@ -284,7 +277,7 @@ void Part::setup(Player *player) {
_pan = clamp(player->getPan(), -64, 63);
_transpose_eff = player->getTranspose();
_transpose = 0;
- _detune = _sysexDetune = 0;
+ _detune = 0;
_detune_eff = player->getDetune();
_pitchbend_factor = 2;
_pitchbend = 0;
diff --git a/engines/scumm/imuse/sysex_scumm.cpp b/engines/scumm/imuse/sysex_scumm.cpp
index 0295b74..6ab71c2 100644
--- a/engines/scumm/imuse/sysex_scumm.cpp
+++ b/engines/scumm/imuse/sysex_scumm.cpp
@@ -72,7 +72,7 @@ void sysexHandler_Scumm(Player *player, const byte *msg, uint16 len) {
part->volume((p[5] & 0x0F) << 4 |(p[6] & 0x0F));
part->set_pan((p[7] & 0x0F) << 4 | (p[8] & 0x0F));
part->_percussion = player->_isMIDI ? ((p[9] & 0x08) > 0) : false;
- part->set_sysexDetune((p[11] & 0x0F) << 4 | (p[12] & 0x0F));
+ part->set_detune((p[11] & 0x0F) << 4 | (p[12] & 0x0F));
part->pitchBendFactor((p[13] & 0x0F) << 4 | (p[14] & 0x0F));
if (part->_percussion) {
if (part->_mc) {
diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h
index 792a31d..776f40e 100644
--- a/engines/scumm/saveload.h
+++ b/engines/scumm/saveload.h
@@ -47,7 +47,7 @@ namespace Scumm {
* only saves/loads those which are valid for the version of the savegame
* which is being loaded/saved currently.
*/
-#define CURRENT_VER 85
+#define CURRENT_VER 84
/**
* An auxillary macro, used to specify savegame versions. We use this instead
Commit: 52e4f162dd60c26eeaf9ea91dae3a2b73af4aa09
https://github.com/scummvm/scummvm/commit/52e4f162dd60c26eeaf9ea91dae3a2b73af4aa09
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:06:48-07:00
Commit Message:
FMTOWNS AUDIO: fix several CppCheck warnings
Changed paths:
audio/softsynth/fmtowns_pc98/towns_audio.cpp
audio/softsynth/fmtowns_pc98/towns_euphony.cpp
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
index f2d249b..dd9bf61 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -255,7 +255,8 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA
_baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver),
_pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume),
_outputVolumeFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0),
- _pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _ready(false) {
+ _pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _fmChanPlaying(0),
+ _numReservedChannels(0), _numWaveTables(0), _ready(false) {
#define INTCB(x) &TownsAudioInterfaceIntern::intf_##x
static const TownsAudioIntfCallback intfCb[] = {
@@ -368,6 +369,11 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA
_intfOpcodes = intfCb;
memset(_fmSaveReg, 0, sizeof(_fmSaveReg));
+ memset(_fmChanNote, 0, sizeof(_fmChanNote));
+ memset(_fmChanPitch, 0, sizeof(_fmChanPitch));
+ memset(_pcmChanNote, 0, sizeof(_pcmChanNote));
+ memset(_pcmChanVelo, 0, sizeof(_pcmChanVelo));
+ memset(_pcmChanLevel, 0, sizeof(_pcmChanLevel));
memset(_outputLevel, 0, sizeof(_outputLevel));
memset(_outputMute, 0, sizeof(_outputMute));
@@ -980,9 +986,9 @@ int TownsAudioInterfaceIntern::intf_setOutputMute(va_list &args) {
memset(_outputMute, 1, 8);
if (mute & 2)
- memset(_outputMute + 12, 1, 4);
+ memset(&_outputMute[12], 1, 4);
if (mute & 1)
- memset(_outputMute + 8, 1, 4);
+ memset(&_outputMute[8], 1, 4);
_outputMute[(f < 0x80) ? 11 : 15] = 0;
f += f;
diff --git a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
index f7aa33f..bc2c88b 100644
--- a/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_euphony.cpp
@@ -28,7 +28,8 @@
TownsEuphonyDriver::TownsEuphonyDriver(Audio::Mixer *mixer) : _activeChannels(0), _sustainChannels(0),
_assignedChannels(0), _paraCount(0), _command(0), _tEnable(0), _tMode(0), _tOrdr(0), _tLevel(0),
_tTranspose(0), _musicPos(0), _musicStart(0), _playing(false), _eventBuffer(0), _bufferedEventsCount(0),
- _tempoControlMode(0) {
+ _tempoControlMode(0), _timerSetting(0), _tempoDiff(0), _timeStampBase(0), _elapsedEvents(0), _loop(false),
+ _endOfTrack(false), _suspendParsing(false), _musicTrackSize(0) {
_para[0] = _para[1] = 0;
_intf = new TownsAudioInterface(mixer, this);
resetTempo();
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 5e7d750..4ff2b98 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -670,7 +670,7 @@ TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanI
}
TownsMidiInputChannel::~TownsMidiInputChannel() {
- delete _instrument;
+ delete[] _instrument;
}
bool TownsMidiInputChannel::allocate() {
@@ -836,7 +836,8 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = {
0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F
};
-MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _open(false) {
+MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _channels(0), _out(0),
+ _chanState(0), _operatorLevelTable(0), _tickCounter1(0), _tickCounter2(0), _rand(1), _allocCurPos(0), _open(false) {
_intf = new TownsAudioInterface(mixer, this);
}
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
index 09d3ca3..46ac7e5 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -99,7 +99,7 @@ TownsPC98_FmSynthOperator::TownsPC98_FmSynthOperator(const uint32 timerbase, con
_rtt(rtt), _rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable),
_sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(timerbase * 2),
_specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0),
- _phase(0), _state(kEnvReady), _holdKey(false), _timer(0), _keyScale1(0),
+ _sustainLevel(0), _phase(0), _state(kEnvReady), _holdKey(false), _timer(0), _keyScale1(0),
_keyScale2(0), _currentLevel(1023), _ampMod(false), _tickCount(0) {
fs_a.rate = fs_a.shift = fs_d.rate = fs_d.shift = fs_s.rate = fs_s.shift = fs_r.rate = fs_r.shift = 0;
@@ -653,7 +653,8 @@ void TownsPC98_FmSynthSquareSineSource::updateRegs() {
#ifndef DISABLE_PC98_RHYTHM_CHANNEL
TownsPC98_FmSynthPercussionSource::TownsPC98_FmSynthPercussionSource(const uint32 timerbase, const uint32 rtt) :
- _rtt(rtt), _tickLength(timerbase * 2), _timer(0), _ready(false), _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) {
+ _rtt(rtt), _tickLength(timerbase * 2), _timer(0), _totalLevel(0), _volMaskA(0), _volMaskB(0),
+ _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume), _ready(false) {
memset(_rhChan, 0, sizeof(RhtChannel) * 6);
_reg = new uint8 *[40];
@@ -1256,7 +1257,7 @@ void TownsPC98_FmSynth::generateTables() {
WRITE_BE_UINT32(_oprRates + 32, _numChan == 6 ? 0x90900000 : 0x00081018);
WRITE_BE_UINT32(_oprRates + 36, _numChan == 6 ? 0x00001010 : 0x00081018);
memset(_oprRates, 0x90, 32);
- memset(_oprRates + 96, 0x80, 32);
+ memset(&_oprRates[96], 0x80, 32);
uint8 *dst = (uint8 *)_oprRates + 40;
for (int i = 0; i < 40; i += 4)
WRITE_BE_UINT32(dst + i, 0x00081018);
@@ -1313,8 +1314,8 @@ void TownsPC98_FmSynth::generateTables() {
uint8 *dtt = new uint8[128];
memset(dtt, 0, 36);
- memset(dtt + 36, 1, 8);
- memcpy(dtt + 44, _detSrc, 84);
+ memset(&dtt[36], 1, 8);
+ memcpy(&dtt[44], _detSrc, 84);
delete[] _oprDetune;
_oprDetune = new int32[256];
Commit: cd359cab1bba820fa8decafb46173201afd02d4a
https://github.com/scummvm/scummvm/commit/cd359cab1bba820fa8decafb46173201afd02d4a
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:07:01-07:00
Commit Message:
GOB: Add a non-interactive Adibou2 demo
Changed paths:
engines/gob/demos/demoplayer.cpp
engines/gob/detection_tables.h
diff --git a/engines/gob/demos/demoplayer.cpp b/engines/gob/demos/demoplayer.cpp
index 5220b45..9aa7a41 100644
--- a/engines/gob/demos/demoplayer.cpp
+++ b/engines/gob/demos/demoplayer.cpp
@@ -50,6 +50,9 @@ DemoPlayer::Script DemoPlayer::_scripts[] = {
"slide xant.imd 20\nslide tum.imd 20\nslide voile.imd 20\n" \
"slide int.imd 20\nslide voila.imd 1\nslide voilb.imd 1\n"},
{kScriptSourceFile, "coktelplayer.scn"},
+ {kScriptSourceFile, "demogb.scn"},
+ {kScriptSourceFile, "demoall.scn"},
+ {kScriptSourceFile, "demofra.scn"}
};
DemoPlayer::DemoPlayer(GobEngine *vm) : _vm(vm) {
diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h
index 79cef9f..11cca2b 100644
--- a/engines/gob/detection_tables.h
+++ b/engines/gob/detection_tables.h
@@ -4791,6 +4791,60 @@ static const GOBGameDescription gameDescriptions[] = {
kFeaturesNone,
0, 0, 0
},
+ {
+ {
+ "adibou2",
+ "Non-Interactive Demo",
+ {
+ {"demogb.scn", 0, "9291455a908ac0e6aaaca686e532609b", 105},
+ {"demogb.vmd", 0, "bc9c1db97db7bec8f566332444fa0090", 14320840},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeAdibou2,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 9
+ },
+ {
+ {
+ "adibou2",
+ "Non-Interactive Demo",
+ {
+ {"demoall.scn", 0, "c8fd308c037b829800006332b2c32674", 106},
+ {"demoall.vmd", 0, "4672b2deacc6fca97484840424b1921b", 14263433},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeAdibou2,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 10
+ },
+ {
+ {
+ "adibou2",
+ "Non-Interactive Demo",
+ {
+ {"demofra.scn", 0, "d1b2b1618af384ea1120def8b986c02b", 106},
+ {"demofra.vmd", 0, "b494cdec1aac7e54c3f2480512d2880e", 14297100},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO_NOSUBTITLES | GUIO_NOSPEECH
+ },
+ kGameTypeAdibou2,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 11
+ },
{ AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0}
};
Commit: 7fd78c59987cfb40560a832c2aef9bf4e71fc39b
https://github.com/scummvm/scummvm/commit/7fd78c59987cfb40560a832c2aef9bf4e71fc39b
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:07:02-07:00
Commit Message:
FM-TOWNS AUDIO: fix GCC warnings
Changed paths:
audio/softsynth/fmtowns_pc98/towns_midi.cpp
audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 4ff2b98..d3d2a66 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -18,8 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL: $
- * $Id: $
*/
#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
@@ -173,7 +171,7 @@ private:
MidiDriver_TOWNS *_driver;
- static const uint8 TownsMidiInputChannel::_programAdjustLevel[];
+ static const uint8 _programAdjustLevel[];
};
class TownsMidiChanState {
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
index 46ac7e5..bc5aa32 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -928,7 +928,7 @@ bool TownsPC98_FmSynth::init() {
}
void TownsPC98_FmSynth::reset() {
- Common::StackLock lock(_mutex);
+ lock();
for (int i = 0; i < _numChan; i++) {
for (int ii = 0; ii < 4; ii++)
_chanInternal[i].opr[ii]->reset();
@@ -948,6 +948,7 @@ void TownsPC98_FmSynth::reset() {
if (_prc)
_prc->reset();
#endif
+ unlock();
}
void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {
Commit: 7a489ef005aea96aa636c83d9f3675e4ec5a58d5
https://github.com/scummvm/scummvm/commit/7a489ef005aea96aa636c83d9f3675e4ec5a58d5
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T13:22:21-07:00
Commit Message:
Merge branch 'master' of git://github.com/scummvm/scummvm
Changed paths:
engines/gob/demos/demoplayer.cpp
engines/gob/detection_tables.h
Commit: 15ea9b15cbb1210b14490819c5bc04f72ed7e6c8
https://github.com/scummvm/scummvm/commit/15ea9b15cbb1210b14490819c5bc04f72ed7e6c8
Author: athrxx (athrxx at scummvm.org)
Date: 2011-05-16T14:13:33-07:00
Commit Message:
SCUMM FM-TOWNS: iMUSE MIDI driver for INDY4/MONKEY2
- This adds an accurate imuse midi driver implementation for the FM-Towns versions of MI2 and INDY4. Until now you could only use the PC devices for these two games (which was not a real issue since the audio tracks are dedicated AdLib and MT-32 tracks anyway; for FM-Towns the AdLib music simply gets converted which is not really satisfactory). Anyway, the new driver it will sound just like when using an emulator like UNZ.
- The YM2612 code was removed since it was not used anymore (except for the the plugin code which was moved to a separate file).
Some explanation about this: The YM2612 code was an incomplete (no instrument support, no pcm support, no proper tempo handling, etc.) implementation of the FM-Towns euphony driver which is used for some sound effects in SCUMM3 games (e.g. LOOM distaff). We do have a rather complete and accurate implementation of that driver in fmtowns_pc98\towns_euphony.cpp (used only in KYRA 1 FM-Towns at first, but also in SCUMM3 since last summer). So this is safe to be removed.
<Auto Generated by Git>
Changed paths:
A audio/softsynth/fmtowns_pc98/towns_midi.cpp
A audio/softsynth/fmtowns_pc98/towns_midi.h
A audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
R audio/softsynth/ym2612.cpp
R audio/softsynth/ym2612.h
audio/module.mk
audio/softsynth/fmtowns_pc98/towns_audio.cpp
audio/softsynth/fmtowns_pc98/towns_audio.h
audio/softsynth/fmtowns_pc98/towns_euphony.cpp
audio/softsynth/fmtowns_pc98/towns_euphony.h
audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
base/plugins.cpp
engines/kyra/sound_towns.cpp
engines/scumm/detection_tables.h
engines/scumm/imuse/sysex_scumm.cpp
engines/scumm/player_towns.cpp
engines/scumm/player_towns.h
engines/scumm/scumm.cpp
engines/scumm/sound.cpp
More information about the Scummvm-git-logs
mailing list