aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorJamieson Christian2003-10-05 15:36:52 +0000
committerJamieson Christian2003-10-05 15:36:52 +0000
commita722d0601e4ae87b15fe09f62b3a1076c6c8646e (patch)
tree511293906e3b210764b047191d68278e4d8cf138 /scumm
parent7174a32c8e877627c51da50b657083873aeef1e6 (diff)
downloadscummvm-rg350-a722d0601e4ae87b15fe09f62b3a1076c6c8646e.tar.gz
scummvm-rg350-a722d0601e4ae87b15fe09f62b3a1076c6c8646e.tar.bz2
scummvm-rg350-a722d0601e4ae87b15fe09f62b3a1076c6c8646e.zip
Preliminary preparation for new YM2612 FM emulator.
All the hooks are in, but actual implementation needs to be checked for portability. svn-id: r10615
Diffstat (limited to 'scumm')
-rw-r--r--scumm/imuse.cpp11
-rw-r--r--scumm/imuse.h13
-rw-r--r--scumm/imuse_internal.h12
-rw-r--r--scumm/imuse_player.cpp31
-rw-r--r--scumm/midiparser_eup.cpp47
-rw-r--r--scumm/scummvm.cpp8
6 files changed, 88 insertions, 34 deletions
diff --git a/scumm/imuse.cpp b/scumm/imuse.cpp
index 223e32ad4f..602627ef4b 100644
--- a/scumm/imuse.cpp
+++ b/scumm/imuse.cpp
@@ -54,6 +54,7 @@ _initialized(false),
_tempoFactor(0),
_player_limit(ARRAYSIZE(_players)),
_recycle_players(false),
+_direct_passthrough(false),
_queue_end(0),
_queue_pos(0),
_queue_sound(0),
@@ -250,7 +251,7 @@ bool IMuseInternal::startSound(int sound) {
return false;
player->clear();
- return player->startSound(sound, driver);
+ return player->startSound(sound, driver, _direct_passthrough);
}
@@ -1117,10 +1118,14 @@ uint32 IMuseInternal::property(int prop, uint32 value) {
break;
case IMuse::PROP_RECYCLE_PLAYERS:
- if (value > 0 && value <= ARRAYSIZE(_players))
- _recycle_players = (value != 0);
+ _recycle_players = (value != 0);
+ break;
+
+ case IMuse::PROP_DIRECT_PASSTHROUGH:
+ _direct_passthrough = (value != 0);
break;
}
+
return 0;
}
diff --git a/scumm/imuse.h b/scumm/imuse.h
index be19ba0372..acebe40529 100644
--- a/scumm/imuse.h
+++ b/scumm/imuse.h
@@ -51,12 +51,13 @@ public:
~IMuse();
enum {
- PROP_TEMPO_BASE = 1,
- PROP_NATIVE_MT32 = 2,
- PROP_MULTI_MIDI = 3,
- PROP_OLD_ADLIB_INSTRUMENTS = 4,
- PROP_LIMIT_PLAYERS = 5,
- PROP_RECYCLE_PLAYERS = 6
+ PROP_TEMPO_BASE,
+ PROP_NATIVE_MT32,
+ PROP_MULTI_MIDI,
+ PROP_OLD_ADLIB_INSTRUMENTS,
+ PROP_LIMIT_PLAYERS,
+ PROP_RECYCLE_PLAYERS,
+ PROP_DIRECT_PASSTHROUGH
};
void on_timer(MidiDriver *midi);
diff --git a/scumm/imuse_internal.h b/scumm/imuse_internal.h
index 0265df65d5..e7e91b3f22 100644
--- a/scumm/imuse_internal.h
+++ b/scumm/imuse_internal.h
@@ -60,10 +60,6 @@ class ScummEngine;
#define TICKS_PER_BEAT 480
-#define IMUSE_SYSEX_ID 0x7D
-#define ROLAND_SYSEX_ID 0x41
-#define PERCUSSION_CHANNEL 9
-
#define TRIGGER_ID 0
#define COMMAND_ID 1
@@ -158,6 +154,7 @@ protected:
protected:
MidiDriver *_midi;
MidiParser *_parser;
+ bool _passThrough; // Only respond to EOT, all else direct to MidiDriver
Part *_parts;
bool _active;
@@ -259,7 +256,7 @@ public:
void setSpeed(byte speed);
int setTranspose(byte relative, int b);
int setVolume(byte vol);
- bool startSound(int sound, MidiDriver *midi);
+ bool startSound(int sound, MidiDriver *midi, bool passThrough);
int getMusicTimer() const;
public:
@@ -366,8 +363,9 @@ protected:
int _tempoFactor;
- int _player_limit; // Limits how many simultaneous music tracks are played
- bool _recycle_players; // Can we stop a player in order to start another one?
+ int _player_limit; // Limits how many simultaneous music tracks are played
+ bool _recycle_players; // Can we stop a player in order to start another one?
+ bool _direct_passthrough; // Pass data direct to MidiDriver (no interactivity)
uint _queue_end, _queue_pos, _queue_sound;
byte _queue_adding;
diff --git a/scumm/imuse_player.cpp b/scumm/imuse_player.cpp
index 69b577ed43..23048341b3 100644
--- a/scumm/imuse_player.cpp
+++ b/scumm/imuse_player.cpp
@@ -39,6 +39,11 @@ namespace Scumm {
//
////////////////////////////////////////
+#define IMUSE_SYSEX_ID 0x7D
+#define YM2612_SYSEX_ID 0x7C
+#define ROLAND_SYSEX_ID 0x41
+#define PERCUSSION_CHANNEL 9
+
extern MidiParser *MidiParser_createRO();
extern MidiParser *MidiParser_createEUP();
@@ -85,7 +90,7 @@ Player::~Player() {
}
}
-bool Player::startSound(int sound, MidiDriver *midi) {
+bool Player::startSound(int sound, MidiDriver *midi, bool passThrough) {
void *ptr;
int i;
@@ -111,6 +116,7 @@ bool Player::startSound(int sound, MidiDriver *midi) {
_pan = 0;
_transpose = 0;
_detune = 0;
+ _passThrough = passThrough;
for (i = 0; i < ARRAYSIZE(_parameterFaders); ++i)
_parameterFaders[i].init();
@@ -152,8 +158,11 @@ void Player::clear() {
debug (0, "Stopping music %d", _id);
#endif
- if (_parser)
+ if (_parser) {
_parser->unloadMusic();
+ delete _parser;
+ _parser = 0;
+ }
uninit_parts();
_se->ImFireAllTriggers(_id);
_active = false;
@@ -224,6 +233,11 @@ void Player::setSpeed(byte speed) {
}
void Player::send(uint32 b) {
+ if (_passThrough) {
+ _midi->send (b);
+ return;
+ }
+
byte cmd = (byte)(b & 0xF0);
byte chan = (byte)(b & 0x0F);
byte param1 = (byte)((b >> 8) & 0xFF);
@@ -333,8 +347,12 @@ void Player::sysEx(byte *p, uint16 len) {
byte buf[128];
Part *part;
+ if (_passThrough) {
+ _midi->sysEx (p, len);
+ return;
+ }
+
// Check SysEx manufacturer.
- // Roland is 0x41
a = *p++;
--len;
if (a != IMUSE_SYSEX_ID) {
@@ -346,6 +364,9 @@ void Player::sysEx(byte *p, uint16 len) {
if (part->clearToTransmit())
part->_instrument.send(part->_mc);
}
+ } else if (a == YM2612_SYSEX_ID) {
+ // FM-Towns custom instrument definition
+ _midi->sysEx_customInstrument (p[0], 'EUP ', p + 1);
} else {
warning("Unknown SysEx manufacturer 0x%02X", (int) a);
}
@@ -1124,10 +1145,8 @@ uint32 Player::getBaseTempo() {
}
void Player::metaEvent(byte type, byte *msg, uint16 len) {
- if (type == 0x2F) {
- _parser->unloadMusic();
+ if (type == 0x2F)
clear();
- }
}
diff --git a/scumm/midiparser_eup.cpp b/scumm/midiparser_eup.cpp
index a094ade5ce..8ba23c1a96 100644
--- a/scumm/midiparser_eup.cpp
+++ b/scumm/midiparser_eup.cpp
@@ -32,6 +32,8 @@ namespace Scumm {
*/
class MidiParser_EUP : public MidiParser {
protected:
+ byte _instruments[6][50]; // Two extra bytes for SysEx ID and channel #
+ byte _channel_instr[16];
struct {
byte *enable;
int8 *channel;
@@ -69,14 +71,22 @@ void MidiParser_EUP::parseNextEvent (EventInfo &info) {
// program changes to get a reasonable "one-size-
// fits-all" sound until we actually support the
// FM synthesis capabilities of FM Towns.
- if (_presend) {
- --_presend;
+ for (; _presend < 32; ++_presend) {
+ if (_channel_instr[_presend >> 1] == 0xFF) continue;
info.start = pos;
info.delta = 0;
- info.event = ((_presend & 1) ? 0xB0 : 0xC0) | (_presend >> 1);
- info.basic.param1 = ((_presend & 1) ? 7 : 0x38);
- info.basic.param2 = ((_presend & 1) ? 127 : 0);
- _presend = (_presend + 2) % 32;
+ if (_presend & 1) {
+ info.event = 0xB0;
+ info.basic.param1 = 7;
+ info.basic.param2 = 127;
+ } else {
+ byte *data = &_instruments[_channel_instr[_presend >> 1]][0];
+ data[1] = _presend >> 1;
+ info.event = 0xF0;
+ info.ext.data = data;
+ info.length = 48;
+ }
+ ++_presend;
return;
}
@@ -89,7 +99,17 @@ void MidiParser_EUP::parseNextEvent (EventInfo &info) {
channel = cmd & 0x0F;
uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _base_tick;
int note = (int) pos[4] + _presets.transpose[preset];
- int volume = (int) pos[5] + _presets.volume[preset];
+ int volume = (int) pos[5];
+ // HACK: Loom-Towns distaff tracks seem to
+ // contain zero-volume note events, so change
+ // those to full volume.
+ if (!volume)
+ volume = 127;
+ volume += _presets.volume[preset];
+ if (volume > 127)
+ volume = 127;
+ else if (volume < 0)
+ volume = 0;
pos += 6;
if (_presets.enable[preset]) {
uint16 duration = pos[1] | (pos[2] << 4);
@@ -148,7 +168,12 @@ bool MidiParser_EUP::loadMusic (byte *data, uint32 size) {
}
byte numInstruments = pos[16];
- pos += (16 + 2 + numInstruments * 48);
+ pos += 16 + 2;
+ for (int i = 0; i < numInstruments; ++i) {
+ _instruments[i][0] = 0x7C;
+ memcpy (&_instruments[i][2], pos, 48);
+ pos += 48;
+ }
// Load the prest pointers
_presets.enable = pos;
@@ -161,6 +186,10 @@ bool MidiParser_EUP::loadMusic (byte *data, uint32 size) {
pos += 32;
pos += 8; // Unknown bytes
+ for (i = 0; i < 16; ++i)
+ _channel_instr[i] = 0xFF;
+ for (i = 0; i < 6; ++i)
+ _channel_instr[pos[i]] = i;
pos += 6; // Instrument-to-channel mapping (not supported yet)
pos += 4; // Skip the music size for now.
pos++; // Unknown byte
@@ -183,7 +212,7 @@ bool MidiParser_EUP::loadMusic (byte *data, uint32 size) {
void MidiParser_EUP::resetTracking() {
MidiParser::resetTracking();
- _presend = 1;
+ _presend = 0;
_base_tick = 0;
}
diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp
index fc8dfa16d0..ad421fb38d 100644
--- a/scumm/scummvm.cpp
+++ b/scumm/scummvm.cpp
@@ -92,15 +92,15 @@ static const TargetSettings scumm_settings[] = {
/* Scumm Version 3 */
{"indy3EGA", "Indiana Jones and the Last Crusade", GID_INDY3, 3, MDT_PCSPK | MDT_ADLIB,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_USE_KEY | GF_16COLOR | GF_OLD_BUNDLE, "00.LFL"},
- {"indy3Towns", "Indiana Jones and the Last Crusade (FM Towns)", GID_INDY3, 3, MDT_ADLIB,
+ {"indy3Towns", "Indiana Jones and the Last Crusade (FM Towns)", GID_INDY3, 3, MDT_TOWNS,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FEW_LOCALS | GF_FMTOWNS | GF_AUDIOTRACKS, "00.LFL"},
{"indy3", "Indiana Jones and the Last Crusade (256)", GID_INDY3, 3, MDT_PCSPK | MDT_ADLIB,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FEW_LOCALS, "00.LFL"},
- {"zak256", "Zak McKracken and the Alien Mindbenders (256)", GID_ZAK256, 3, MDT_ADLIB,
+ {"zak256", "Zak McKracken and the Alien Mindbenders (256)", GID_ZAK256, 3, MDT_TOWNS,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FMTOWNS | GF_AUDIOTRACKS, "00.LFL"},
{"loom", "Loom", GID_LOOM, 3, MDT_PCSPK | MDT_ADLIB | MDT_NATIVE,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_USE_KEY | GF_16COLOR | GF_OLD_BUNDLE, "00.LFL"},
- {"loomTowns", "Loom (FM Towns)", GID_LOOM, 3, MDT_ADLIB,
+ {"loomTowns", "Loom (FM Towns)", GID_LOOM, 3, MDT_TOWNS,
GF_SMALL_HEADER | GF_SMALL_NAMES | GF_NO_SCALING | GF_OLD256 | GF_FMTOWNS | GF_AUDIOTRACKS, "00.LFL"},
/* Scumm Version 4 */
@@ -696,6 +696,8 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst)
_imuse->property(IMuse::PROP_LIMIT_PLAYERS, 1);
_imuse->property(IMuse::PROP_RECYCLE_PLAYERS, 1);
}
+ if (_features & GF_FMTOWNS)
+ _imuse->property(IMuse::PROP_DIRECT_PASSTHROUGH, 1);
_imuse->set_music_volume(_sound->_sound_volume_music);
}
}