scummvm/backends/midi/stmidi.cpp
2018-08-18 14:08:40 +02:00

159 lines
4.3 KiB
C++

/* 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.
*
*/
/*
* Raw MIDI output for the Atari ST line of computers.
* Based on the ScummVM SEQ & CoreMIDI drivers.
* Atari code by Keith Scroggins
* We, unfortunately, could not use the SEQ driver because the /dev/midi under
* FreeMiNT (and hence in libc) is considered to be a serial port for machine
* access. So, we just use OS calls then to send the data to the MIDI ports
* directly. The current implementation is sending 1 byte at a time because
* in most cases we are only sending up to 3 bytes, I believe this saves a few
* cycles. I might change so sysex messages are sent the other way later.
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/scummsys.h"
#if defined(__MINT__)
#include <osbind.h>
#include "audio/mpu401.h"
#include "common/error.h"
#include "common/util.h"
#include "audio/musicplugin.h"
class MidiDriver_STMIDI : public MidiDriver_MPU401 {
public:
MidiDriver_STMIDI() : _isOpen (false) { }
int open();
bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
private:
bool _isOpen;
};
int MidiDriver_STMIDI::open() {
if (_isOpen && (!Bcostat(4)))
return MERR_ALREADY_OPEN;
warning("ST Midi Port Open");
_isOpen = true;
return 0;
}
void MidiDriver_STMIDI::close() {
MidiDriver_MPU401::close();
_isOpen = false;
}
void MidiDriver_STMIDI::send(uint32 b) {
byte status_byte = (b & 0x000000FF);
byte first_byte = (b & 0x0000FF00) >> 8;
byte second_byte = (b & 0x00FF0000) >> 16;
// warning("ST MIDI Packet sent");
switch (b & 0xF0) {
case 0x80: // Note Off
case 0x90: // Note On
case 0xA0: // Polyphonic Key Pressure
case 0xB0: // Controller
case 0xE0: // Pitch Bend
Bconout(3, status_byte);
Bconout(3, first_byte);
Bconout(3, second_byte);
break;
case 0xC0: // Program Change
case 0xD0: // Aftertouch
Bconout(3, status_byte);
Bconout(3, first_byte);
break;
default:
fprintf(stderr, "Unknown : %08x\n", (int)b);
break;
}
}
void MidiDriver_STMIDI::sysEx (const byte *msg, uint16 length) {
// FIXME: LordHoto doesn't know if this will still work
// when sending 264 byte sysEx data, as needed by KYRA,
// feel free to revert it to 254 again if needed.
if (length > 264) {
warning ("Cannot send SysEx block - data too large");
return;
}
const byte *chr = msg;
warning("Sending SysEx Message");
Bconout(3, '0xF0');
for (; length; --length, ++chr) {
Bconout(3,((unsigned char) *chr & 0x7F));
}
Bconout(3, '0xF7');
}
// Plugin interface
class StMidiMusicPlugin : public MusicPluginObject {
public:
const char *getName() const {
return "STMIDI";
}
const char *getId() const {
return "stmidi";
}
MusicDevices getDevices() const;
Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices StMidiMusicPlugin::getDevices() const {
MusicDevices devices;
// TODO: Return a different music type depending on the configuration
// TODO: List the available devices
devices.push_back(MusicDevice(this, "", MT_GM));
return devices;
}
Common::Error StMidiMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_STMIDI();
return Common::kNoError;
}
//#if PLUGIN_ENABLED_DYNAMIC(STMIDI)
//REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#else
REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#endif
#endif