synced with scummvm to 2011-Apr-13

This commit is contained in:
Pawel Kolodziejski 2011-04-14 12:41:26 +02:00
parent f0a4299aef
commit 0640dcf2c7
347 changed files with 53648 additions and 8521 deletions

View File

@ -1,3 +1,9 @@
NOTE: Only certain parts of the Residual project are under the GNU LGPL.
The majority of the files are under the GNU GPL. See the headers of the
individual files to find out the exact license.
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999

View File

@ -26,7 +26,7 @@ ifeq "$(HAVE_GCC)" "1"
CXXFLAGS+= -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder
# Enable even more warnings...
CXXFLAGS+= -Wpointer-arith -Wcast-qual
CXXFLAGS+= -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings
CXXFLAGS+= -Wshadow -Wnon-virtual-dtor -Wwrite-strings
# Currently we disable this gcc flag, since it will also warn in cases,
# where using GCC_PRINTF (means: __attribute__((format(printf, x, y))))
@ -48,9 +48,12 @@ ifeq "$(HAVE_CLANG)" "1"
CXXFLAGS+= -Wno-conversion -Wno-shorten-64-to-32 -Wno-sign-compare -Wno-four-char-constants
endif
# Warn if global constructors are used. Only available in GCC with LLVM backend
# (and maybe clang?), hence off by default.
#CXXFLAGS+= -Wglobal-constructors
ifeq "$(HAVE_ICC)" "1"
# Disable some warnings:
# 161: unrecognized #pragma
# 1899: multicharacter character literal (potential portability problem)
CXXFLAGS+= -diag-disable 161,1899
endif
#######################################################################
# Default commands - put the necessary replacements in config.mk #
@ -69,7 +72,7 @@ ZIP ?= zip -q
# Misc stuff - you should never have to edit this #
#######################################################################
EXECUTABLE := residual$(EXEEXT)
EXECUTABLE := $(EXEPRE)residual$(EXEEXT)
include $(srcdir)/Makefile.common

View File

@ -16,22 +16,22 @@ all: $(EXECUTABLE) plugins
######################################################################
PLUGINS :=
MODULES := base $(MODULES)
MODULES := devtools base $(MODULES)
-include $(srcdir)/engines/engines.mk
# After the game specific modules follow the shared modules
MODULES += \
gui \
sound \
backends \
engines \
graphics \
audio \
common \
po
ifdef USE_MT32EMU
MODULES += sound/softsynth/mt32
MODULES += audio/softsynth/mt32
endif
######################################################################
@ -54,6 +54,10 @@ DEPFILES =
# the build date in gScummVMBuildDate is correct.
base/version.o: $(filter-out base/libbase.a,$(OBJS))
ifdef USE_ELF_LOADER
backends/plugins/elf/version.o: $(filter-out base/libbase.a,$(filter-out backends/libbackends.a,$(OBJS)))
endif
# Replace regular output with quiet messages
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifneq ($(VERBOSE_BUILD),1)
@ -158,34 +162,36 @@ VER_EXTRA = $(shell echo $(VERSION) | cut -d. -f 3 | cut -c2-)
######################################################################
# Get Subversion's working copy information
# Get git's working copy information
######################################################################
ifneq ($(shell svn info $(srcdir) 1>/dev/null 2>&1 || echo "error"),error)
SVNROOT := $(srcdir)
ifeq ($(origin VER_SVNREV), undefined)
ifneq ($(shell cd $(srcdir); git rev-parse --verify HEAD 1>/dev/null 2>&1 || echo "error"),error)
GITROOT := $(srcdir)
ifeq ($(origin VER_REV), undefined)
# Are there uncommitted changes? (describe --dirty is only available since 1.6.6)
VER_DIRTY := $(shell cd $(srcdir); git update-index --refresh --unmerged 1>/dev/null 2>&1; git diff-index --quiet HEAD || echo "-dirty")
# Get the working copy base revision
VER_SVNREV := $(shell LANG=C svn info $(SVNROOT) | grep "^Revision" | cut -d ' ' -f 2)
VER_REV := $(shell cd $(srcdir); git describe --match desc/\* | cut -d '-' -f 2-)$(VER_DIRTY)
endif
else
SVNROOT := https://resisual.svn.sourceforge.net/svnroot/residual/residual/trunk/
GITROOT := git://github.com/residual/residual.git
endif
# Define the Subversion revision if available, either autodetected or
# specified by the user, but only for base/version.cpp.
ifneq ($(origin VER_SVNREV), undefined)
CXXFLAGS+= -DRESIDUAL_SVN_REVISION=\"$(VER_SVNREV)\"
ifneq ($(origin VER_REV), undefined)
base/version.o: CXXFLAGS:=$(CXXFLAGS) -DRESIDUAL_REVISION=\"$(VER_REV)\"
endif
######################################################################
# Distribution settings
######################################################################
ifeq ($(VER_EXTRA),svn)
ifeq ($(origin VER_SVNREV), undefined)
ifeq ($(VER_EXTRA),git)
ifeq ($(origin VER_REV), undefined)
DISTVERSION = $(shell date '+%Y-%m-%d')
else
DISTVERSION = svn$(VER_SVNREV)
DISTVERSION = git$(VER_REV)
endif
else
DISTVERSION = $(VERSION)
@ -195,14 +201,15 @@ DISTNAME := residual-$(DISTVERSION)
DISTDIR := dist
VERFILE := $(DISTDIR)/$(DISTNAME)/base/internal_version.h
# TODO git via $(GITROOT)
$(VERFILE): $(srcdir)/base/internal_version.h
@$(RM_REC) $(DISTDIR)
@$(MKDIR) $(DISTDIR)
svn export $(SVNROOT) $(DISTDIR)/$(DISTNAME)
ifneq ($(origin VER_SVNREV), undefined)
ifneq ($(origin VER_REV), undefined)
@# Use the current SVN revision as a default for the snapshot sources
@svn cat $(SVNROOT)/base/internal_version.h | sed -e \
"s/^#define RESIDUAL_SVN_REVISION$$/#define RESIDUAL_SVN_REVISION \"$(VER_SVNREV)\"/g" \
"s/^#define RESIDUAL_REVISION$$/#define RESIDUAL_REVISION \"$(VER_REV)\"/g" \
> $(VERFILE)
endif

View File

@ -29,12 +29,12 @@
#include "common/queue.h"
#include "common/util.h"
#include "sound/audiostream.h"
#include "sound/decoders/flac.h"
#include "sound/mixer.h"
#include "sound/decoders/mp3.h"
#include "sound/decoders/raw.h"
#include "sound/decoders/vorbis.h"
#include "audio/audiostream.h"
#include "audio/decoders/flac.h"
#include "audio/mixer.h"
#include "audio/decoders/mp3.h"
#include "audio/decoders/raw.h"
#include "audio/decoders/vorbis.h"
namespace Audio {
@ -228,8 +228,8 @@ int SubLoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
SubSeekableAudioStream::SubSeekableAudioStream(SeekableAudioStream *parent, const Timestamp start, const Timestamp end, DisposeAfterUse::Flag disposeAfterUse)
: _parent(parent), _disposeAfterUse(disposeAfterUse),
_start(convertTimeToStreamPos(start, getRate(), isStereo())),
_pos(0, getRate() * (isStereo() ? 2 : 1)),
_length(convertTimeToStreamPos(end - start, getRate(), isStereo())) {
_pos(0, getRate() * (isStereo() ? 2 : 1)),
_length(convertTimeToStreamPos(end, getRate(), isStereo()) - _start) {
assert(_length.totalNumberOfFrames() % (isStereo() ? 2 : 1) == 0);
_parent->seek(_start);
@ -393,7 +393,7 @@ Timestamp convertTimeToStreamPos(const Timestamp &where, int rate, bool isStereo
//
// An example is when converting the timestamp 500ms to a 11025 Hz based
// stream. It would have an internal frame counter of 5512.5. Now when
// doing calculations at frame precision, this might lead to unexpected
// doing calculations at frame precision, this might lead to unexpected
// results: The frame difference between a timestamp 1000ms and the above
// mentioned timestamp (both with 11025 as framerate) would be 5512,
// instead of 5513, which is what a frame-precision based code would expect.

View File

@ -30,7 +30,7 @@
#include "common/sys.h"
#include "common/types.h"
#include "sound/timestamp.h"
#include "audio/timestamp.h"
namespace Audio {
@ -276,11 +276,6 @@ private:
* The same caveats apply to SubSeekableAudioStream as do to SeekableAudioStream.
*
* Manipulating the parent stream directly /will/ mess up a substream.
*
* IMPORTANT:
* Note for engine authors. This object is currently under inspection. In case
* we need to revise the looping API we might drop this. So if you really need
* something like this object, please drop a mail to LordHoto.
*/
class SubSeekableAudioStream : public SeekableAudioStream {
public:

View File

@ -23,7 +23,10 @@
*
*/
#include "sound/decoders/flac.h"
// Disable symbol overrides for FILE as that is used in FLAC headers
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
#include "audio/decoders/flac.h"
#ifdef USE_FLAC
@ -31,8 +34,7 @@
#include "common/stream.h"
#include "common/util.h"
#include "sound/audiostream.h"
#include "sound/audiocd.h"
#include "audio/audiostream.h"
#define FLAC__NO_DLL // that MS-magic gave me headaches - just link the library you like
#include <FLAC/export.h>
@ -140,7 +142,7 @@ public:
bool seek(const Timestamp &where);
Timestamp getLength() const { return _length; }
bool isStreamDecoderReady() const { return getStreamDecoderState() == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC ; }
bool isStreamDecoderReady() const { return getStreamDecoderState() == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; }
protected:
uint getChannels() const { return MIN<uint>(_streaminfo.channels, MAX_OUTPUT_CHANNELS); }
@ -303,7 +305,7 @@ int FLACStream::readBuffer(int16 *buffer, const int numSamples) {
const uint numChannels = getChannels();
if (numChannels == 0) {
warning("FLACStream: Stream not sucessfully initialised, cant playback");
warning("FLACStream: Stream not successfully initialised, cant playback");
return -1; // streaminfo wasnt read!
}
@ -553,7 +555,7 @@ void FLACStream::convertBuffersGeneric(SampleType* bufDestination, const FLAC__i
for (; numSamples > 0; numSamples -= numChannels) {
for (uint i = 0; i < numChannels; ++i)
*bufDestination++ = static_cast<SampleType>(*(inChannels[i]++) >> kPower) ;
*bufDestination++ = static_cast<SampleType>(*(inChannels[i]++) >> kPower);
}
} else {
for (; numSamples > 0; numSamples -= numChannels) {

View File

@ -27,10 +27,12 @@
* @file
* Sound decoder used in engines:
* - agos
* - draci
* - kyra
* - m4
* - queen
* - saga
* - sci
* - scumm
* - sword1
* - sword2

View File

@ -23,7 +23,7 @@
*
*/
#include "sound/decoders/mp3.h"
#include "audio/decoders/mp3.h"
#ifdef USE_MAD
@ -31,8 +31,7 @@
#include "common/stream.h"
#include "common/util.h"
#include "sound/audiocd.h"
#include "sound/audiostream.h"
#include "audio/audiostream.h"
#include <mad.h>

View File

@ -27,10 +27,13 @@
* @file
* Sound decoder used in engines:
* - agos
* - draci
* - kyra
* - m4
* - mohawk
* - queen
* - saga
* - sci
* - scumm
* - sword1
* - sword2

View File

@ -24,11 +24,11 @@
*/
#include "common/endian.h"
#include "common/stream.h"
#include "common/memstream.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
#include "sound/decoders/raw.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
#include "audio/decoders/raw.h"
namespace Audio {

View File

@ -23,7 +23,12 @@
*
*/
#include "sound/decoders/vorbis.h"
// Disable symbol overrides for FILE and fseek as those are used in the
// Vorbis headers.
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
#define FORBIDDEN_SYMBOL_EXCEPTION_fseek
#include "audio/decoders/vorbis.h"
#ifdef USE_VORBIS
@ -31,8 +36,7 @@
#include "common/stream.h"
#include "common/util.h"
#include "sound/audiostream.h"
#include "sound/audiocd.h"
#include "audio/audiostream.h"
#ifdef USE_TREMOR
#if defined(__GP32__) // custom libtremor locations

View File

@ -27,10 +27,12 @@
* @file
* Sound decoder used in engines:
* - agos
* - draci
* - kyra
* - m4
* - queen
* - saga
* - sci
* - scumm
* - sword1
* - sword2

View File

@ -22,10 +22,10 @@
* $Id$
*/
#include "sound/fmopl.h"
#include "audio/fmopl.h"
#include "sound/softsynth/opl/dosbox.h"
#include "sound/softsynth/opl/mame.h"
#include "audio/softsynth/opl/dosbox.h"
#include "audio/softsynth/opl/mame.h"
#include "common/config-manager.h"
#include "common/translation.h"

View File

@ -28,8 +28,8 @@
#include "common/str.h"
#include "common/system.h"
#include "common/util.h"
#include "sound/mididrv.h"
#include "sound/musicplugin.h"
#include "audio/mididrv.h"
#include "audio/musicplugin.h"
#include "common/translation.h"
const byte MidiDriver::_mt32ToGm[128] = {
@ -162,7 +162,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
case MT_AMIGA:
if (flags & MDT_AMIGA)
return hdl;
break;
break;
case MT_APPLEIIGS:
if (flags & MDT_APPLEIIGS)
@ -209,35 +209,40 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
hdl = getDeviceHandle("auto");
const MusicType type = getMusicType(hdl);
if (type != MT_AUTO && type != MT_INVALID) {
if (flags & MDT_PREFER_MT32)
// If we have a preferred MT32 device we disable the gm/mt32 mapping (more about this in mididrv.h)
_forceTypeMT32 = true;
return hdl;
}
// If have a "Don't use GM/MT-32" setting we skip this part and jump
// to AdLib, PC Speaker etc. detection right away.
if (type != MT_NULL) {
if (type != MT_AUTO && type != MT_INVALID) {
if (flags & MDT_PREFER_MT32)
// If we have a preferred MT32 device we disable the gm/mt32 mapping (more about this in mididrv.h)
_forceTypeMT32 = true;
// If we have no specific device selected (neither in the scummvm nor in the game domain)
// and no preferred MT32 or GM device selected we arrive here.
// If MT32 is preferred we try for the first available device with music type 'MT_MT32' (usually the mt32 emulator)
if (flags & MDT_PREFER_MT32) {
return hdl;
}
// If we have no specific device selected (neither in the scummvm nor in the game domain)
// and no preferred MT32 or GM device selected we arrive here.
// If MT32 is preferred we try for the first available device with music type 'MT_MT32' (usually the mt32 emulator)
if (flags & MDT_PREFER_MT32) {
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getMusicType() == MT_MT32)
return d->getHandle();
}
}
}
// Now we default to the first available device with music type 'MT_GM'
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getMusicType() == MT_MT32)
if (d->getMusicType() == MT_GM || d->getMusicType() == MT_GS)
return d->getHandle();
}
}
}
// Now we default to the first available device with music type 'MT_GM'
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getMusicType() == MT_GM || d->getMusicType() == MT_GS)
return d->getHandle();
}
}
}
MusicType tp = MT_AUTO;
@ -247,10 +252,10 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
tp = MT_PC98;
else if (flags & MDT_ADLIB)
tp = MT_ADLIB;
else if (flags & MDT_PCSPK)
tp = MT_PCSPK;
else if (flags & MDT_PCJR)
tp = MT_PCJR;
else if (flags & MDT_PCSPK)
tp = MT_PCSPK;
else if (flags & MDT_C64)
tp = MT_C64;
else if (flags & MDT_AMIGA)

View File

@ -37,15 +37,6 @@ namespace Audio {
}
namespace Common { class String; }
/**
* Music Driver Types, used to uniquely identify each music driver.
*
* The pseudo drivers are listed first, then all native drivers,
* then all other MIDI drivers, and finally the non-MIDI drivers.
*
* @todo Rename MidiDriverType to MusicDriverType
*/
/**
* Music types that music drivers can implement and engines can rely on.
*/
@ -71,16 +62,21 @@ enum MusicType {
* A set of flags to be passed to detectDevice() which can be used to
* specify what kind of music driver is preferred / accepted.
*
* The flags (except for MDT_PREFER_MT32 and MDT_PREFER_GM) indicate whether a given driver
* type is acceptable. E.g. the TOWNS music driver could be returned by
* detectDevice if and only if MDT_TOWNS is specified.
* The flags (except for MDT_PREFER_MT32 and MDT_PREFER_GM) indicate whether a
* given driver type is acceptable. E.g. the TOWNS music driver could be
* returned by detectDevice if and only if MDT_TOWNS is specified.
*
* MDT_PREFER_MT32 and MDT_PREFER_GM indicate the MIDI device type to use when
* no device is selected in the music options, or when the MIDI device selected
* does not match the requirements of a game engine. With these flags, more
* priority is given to an MT-32 device, or a GM device respectively.
*
* @todo Rename MidiDriverFlags to MusicDriverFlags
*/
enum MidiDriverFlags {
MDT_NONE = 0,
MDT_PCSPK = 1 << 0, // PC Speaker: Maps to MD_PCSPK and MD_PCJR
MDT_CMS = 1 << 1, // Creative Music System / Gameblaster: Maps to MD_CMS
MDT_PCSPK = 1 << 0, // PC Speaker: Maps to MT_PCSPK and MT_PCJR
MDT_CMS = 1 << 1, // Creative Music System / Gameblaster: Maps to MT_CMS
MDT_PCJR = 1 << 2, // Tandy/PC Junior driver
MDT_ADLIB = 1 << 3, // AdLib: Maps to MT_ADLIB
MDT_C64 = 1 << 4,
@ -94,19 +90,53 @@ enum MidiDriverFlags {
};
/**
* Abstract description of a MIDI driver. Used by the config file and command
* line parsing code, and also to be able to give the user a list of available
* drivers.
*
* @todo Rename MidiDriverType to MusicDriverType
* TODO: Document this, give it a better name.
*/
class MidiDriver_BASE {
public:
virtual ~MidiDriver_BASE() { }
/**
* Output a packed midi command to the midi stream.
* The 'lowest' byte (i.e. b & 0xFF) is the status
* code, then come (if used) the first and second
* opcode.
*/
virtual void send(uint32 b) = 0;
/**
* Output a midi command to the midi stream. Convenience wrapper
* around the usual 'packed' send method.
*
* Do NOT use this for sysEx transmission; instead, use the sysEx()
* method below.
*/
void send(byte status, byte firstOp, byte secondOp) {
send(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
}
/**
* Transmit a sysEx to the midi device.
*
* The given msg MUST NOT contain the usual SysEx frame, i.e.
* do NOT include the leading 0xF0 and the trailing 0xF7.
*
* Furthermore, the maximal supported length of a SysEx
* is 264 bytes. Passing longer buffers can lead to
* undefined behavior (most likely, a crash).
*/
virtual void sysEx(const byte *msg, uint16 length) { }
// TODO: Document this.
virtual void metaEvent(byte type, byte *data, uint16 length) { }
};
/**
* Abstract MIDI Driver Class
*
* @todo Rename MidiDriver to MusicDriver
*/
class MidiDriver {
class MidiDriver : public MidiDriver_BASE {
public:
/**
* The device handle.
@ -130,7 +160,7 @@ public:
/** Returns device handle based on the present devices and the flags parameter. */
static DeviceHandle detectDevice(int flags);
/** Find the music driver matching the given driver name/description. */
static DeviceHandle getDeviceHandle(const Common::String &identifier);
@ -177,28 +207,14 @@ public:
*/
virtual int open() = 0;
/**
* Check whether the midi driver has already been opened.
*/
virtual bool isOpen() const = 0;
/** Close the midi driver. */
virtual void close() = 0;
/**
* Output a packed midi command to the midi stream.
* The 'lowest' byte (i.e. b & 0xFF) is the status
* code, then come (if used) the first and second
* opcode.
*/
virtual void send(uint32 b) = 0;
/**
* Output a midi command to the midi stream. Convenience wrapper
* around the usual 'packed' send method.
*
* Do NOT use this for sysEx transmission; instead, use the sysEx()
* method below.
*/
void send(byte status, byte firstOp, byte secondOp) {
send(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
}
/** Get or set a property. */
virtual uint32 property(int prop, uint32 param) { return 0; }
@ -225,22 +241,8 @@ public:
*/
void sendGMReset();
/**
* Transmit a sysEx to the midi device.
*
* The given msg MUST NOT contain the usual SysEx frame, i.e.
* do NOT include the leading 0xF0 and the trailing 0xF7.
*
* Furthermore, the maximal supported length of a SysEx
* is 264 bytes. Passing longer buffers can lead to
* undefined behavior (most likely, a crash).
*/
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) { }
// Timing functions - MidiDriver now operates timers
virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) = 0;

View File

@ -23,8 +23,8 @@
*
*/
#include "sound/midiparser.h"
#include "sound/mididrv.h"
#include "audio/midiparser.h"
#include "audio/mididrv.h"
#include "common/util.h"
//////////////////////////////////////////////////
@ -43,6 +43,7 @@ _psec_per_tick(5208), // 500000 / 96
_autoLoop(false),
_smartJump(false),
_centerPitchWheelOnUnload(false),
_sendSustainOffOnNotesOff(false),
_num_tracks(0),
_active_track(255),
_abort_parse(0) {
@ -64,6 +65,9 @@ void MidiParser::property(int prop, int value) {
case mpCenterPitchWheelOnUnload:
_centerPitchWheelOnUnload = (value != 0);
break;
case mpSendSustainOffOnNotesOff:
_sendSustainOffOnNotesOff = (value != 0);
break;
}
}
@ -281,6 +285,8 @@ void MidiParser::allNotesOff() {
for (i = 0; i < 16; ++i) {
sendToDriver(0xB0 | i, 0x7b, 0); // All notes off
if (_sendSustainOffOnNotesOff)
sendToDriver(0xB0 | i, 0x40, 0); // Also send a sustain off event (bug #3116608)
}
memset(_active_notes, 0, sizeof(_active_notes));
@ -344,7 +350,7 @@ void MidiParser::hangAllActiveNotes() {
if (_next_event.command() == 0x8) {
if (temp_active[_next_event.basic.param1] & (1 << _next_event.channel())) {
hangingNote(_next_event.channel(), _next_event.basic.param1, (advance_tick - _position._last_event_tick) * _psec_per_tick, false);
temp_active[_next_event.basic.param1] &= ~ (1 << _next_event.channel());
temp_active[_next_event.basic.param1] &= ~(1 << _next_event.channel());
}
} else if (_next_event.event == 0xFF && _next_event.ext.type == 0x2F) {
// warning("MidiParser::hangAllActiveNotes(): Hit End of Track with active notes left");
@ -361,7 +367,7 @@ void MidiParser::hangAllActiveNotes() {
}
}
bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes) {
bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes, bool dontSendNoteOn) {
if (_active_track >= _num_tracks)
return false;
@ -402,8 +408,17 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes) {
_driver->sysEx(info.ext.data, (uint16)info.length-1);
else
_driver->sysEx(info.ext.data, (uint16)info.length);
} else
sendToDriver(info.event, info.basic.param1, info.basic.param2);
} else {
// The note on sending code is used by the SCUMM engine. Other engine using this code
// (such as SCI) have issues with this, as all the notes sent can be heard when a song
// is fast-forwarded. Thus, if the engine requests it, don't send note on events.
if (info.command() == 0x9 && dontSendNoteOn) {
// Don't send note on; doing so creates a "warble" with some instruments on the MT-32.
// Refer to patch #3117577
} else {
sendToDriver(info.event, info.basic.param1, info.basic.param2);
}
}
}
parseNextEvent(_next_event);

View File

@ -32,7 +32,7 @@
#include "common/endian.h"
class MidiParser;
class MidiDriver;
class MidiDriver_BASE;
@ -273,7 +273,7 @@ protected:
///< Used for "Smart Jump" and MIDI formats that do not include explicit Note Off events.
byte _hanging_notes_count; ///< Count of hanging notes, used to optimize expiration.
MidiDriver *_driver; ///< The device to which all events will be transmitted.
MidiDriver_BASE *_driver; ///< The device to which all events will be transmitted.
uint32 _timer_rate; ///< The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
uint32 _ppqn; ///< Pulses Per Quarter Note. (We refer to "pulses" as "ticks".)
uint32 _tempo; ///< Microseconds per quarter note.
@ -281,7 +281,7 @@ protected:
bool _autoLoop; ///< For lightweight clients that don't provide their own flow control.
bool _smartJump; ///< Support smart expiration of hanging notes when jumping
bool _centerPitchWheelOnUnload; ///< Center the pitch wheels when unloading a song
bool _sendSustainOffOnNotesOff; ///< Send a sustain off on a notes off event, stopping hanging notes
byte *_tracks[120]; ///< Multi-track MIDI formats are supported, up to 120 tracks.
byte _num_tracks; ///< Count of total tracks for multi-track MIDI formats. 1 for single-track formats.
byte _active_track; ///< Keeps track of the currently active track, in multi-track formats.
@ -361,7 +361,13 @@ public:
* Center the pitch wheels when unloading music in preparation
* for the next piece of music.
*/
mpCenterPitchWheelOnUnload = 4
mpCenterPitchWheelOnUnload = 4,
/**
* Sends a sustain off event when a notes off event is triggered.
* Stops hanging notes.
*/
mpSendSustainOffOnNotesOff = 5
};
public:
@ -374,7 +380,7 @@ public:
virtual void unloadMusic();
virtual void property(int prop, int value);
void setMidiDriver(MidiDriver *driver) { _driver = driver; }
void setMidiDriver(MidiDriver_BASE *driver) { _driver = driver; }
void setTimerRate(uint32 rate) { _timer_rate = rate; }
void setTempo(uint32 tempo);
void onTimer();
@ -383,7 +389,7 @@ public:
void stopPlaying();
bool setTrack(int track);
bool jumpToTick(uint32 tick, bool fireEvents = false, bool stopNotes = true);
bool jumpToTick(uint32 tick, bool fireEvents = false, bool stopNotes = true, bool dontSendNoteOn = false);
uint32 getPPQN() { return _ppqn; }
virtual uint32 getTick() { return _position._play_tick; }

View File

@ -26,10 +26,10 @@
#include "common/util.h"
#include "common/system.h"
#include "sound/mixer_intern.h"
#include "sound/rate.h"
#include "sound/audiostream.h"
#include "sound/timestamp.h"
#include "audio/mixer_intern.h"
#include "audio/rate.h"
#include "audio/audiostream.h"
#include "audio/timestamp.h"
namespace Audio {
@ -54,8 +54,9 @@ public:
* @param len number of sample *pairs*. So a value of
* 10 means that the buffer contains twice 10 sample, each
* 16 bits, for a total of 40 bytes.
* @return number of sample pairs processed (which can still be silence!)
*/
void mix(int16 *data, uint len);
int mix(int16 *data, uint len);
/**
* Queries whether the channel is still playing or not.
@ -257,7 +258,7 @@ void MixerImpl::playStream(
insertChannel(handle, chan);
}
void MixerImpl::mixCallback(byte *samples, uint len) {
int MixerImpl::mixCallback(byte *samples, uint len) {
assert(samples);
Common::StackLock lock(_mutex);
@ -272,14 +273,21 @@ void MixerImpl::mixCallback(byte *samples, uint len) {
memset(buf, 0, 2 * len * sizeof(int16));
// mix all channels
int res = 0, tmp;
for (int i = 0; i != NUM_CHANNELS; i++)
if (_channels[i]) {
if (_channels[i]->isFinished()) {
delete _channels[i];
_channels[i] = 0;
} else if (!_channels[i]->isPaused())
_channels[i]->mix(buf, len);
} else if (!_channels[i]->isPaused()) {
tmp = _channels[i]->mix(buf, len);
if (tmp > res)
res = tmp;
}
}
return res;
}
void MixerImpl::stopAll() {
@ -538,19 +546,23 @@ Timestamp Channel::getElapsedTime() {
return ts;
}
void Channel::mix(int16 *data, uint len) {
int Channel::mix(int16 *data, uint len) {
assert(_stream);
int res = 0;
if (_stream->endOfData()) {
// TODO: call drain method
} else {
assert(_converter);
_samplesConsumed = _samplesDecoded;
_mixerTimeStamp = g_system->getMillis();
_pauseTime = 0;
_samplesDecoded += _converter->flow(*_stream, data, len, _volL, _volR);
res = _converter->flow(*_stream, data, len, _volL, _volR);
_samplesDecoded += res;
}
return res;
}
} // End of namespace Audio

View File

@ -28,8 +28,9 @@
#include "common/types.h"
#include "common/mutex.h"
#include "common/noncopyable.h"
#include "sound/timestamp.h"
#include "audio/timestamp.h"
class OSystem;
@ -37,8 +38,6 @@ class OSystem;
namespace Audio {
class AudioStream;
class RewindableAudioStream;
class SeekableAudioStream;
class Channel;
class Mixer;
class MixerImpl;
@ -61,7 +60,7 @@ public:
* The main audio mixer handles mixing of an arbitrary number of
* audio streams (in the form of AudioStream instances).
*/
class Mixer {
class Mixer : Common::NonCopyable {
public:
enum SoundType {
kPlainSoundType = 0,

View File

@ -28,7 +28,7 @@
#include "common/sys.h"
#include "common/mutex.h"
#include "sound/mixer.h"
#include "audio/mixer.h"
namespace Audio {
@ -118,8 +118,10 @@ public:
* The mixer callback function, to be called at regular intervals by
* the backend (e.g. from an audio mixing thread). All the actual mixing
* work is done from here.
*
* @return number of sample pairs processed (which can still be silence!)
*/
void mixCallback(byte *samples, uint len);
int mixCallback(byte *samples, uint len);
/**
* Set the internal 'is ready' flag of the mixer.

View File

@ -1,7 +1,6 @@
MODULE := sound
MODULE := audio
MODULE_OBJS := \
audiocd.o \
audiostream.o \
fmopl.o \
mididrv.o \

View File

@ -22,7 +22,7 @@
* $Id$
*/
#include "sound/mpu401.h"
#include "audio/mpu401.h"
#include "common/system.h"
#include "common/timer.h"
#include "common/util.h" // for ARRAYSIZE
@ -101,12 +101,18 @@ MidiDriver_MPU401::MidiDriver_MPU401() :
}
}
MidiDriver_MPU401::~MidiDriver_MPU401() {
}
void MidiDriver_MPU401::close() {
if (_timer_proc)
if (_timer_proc) {
g_system->getTimerManager()->removeTimerProc(_timer_proc);
_timer_proc = 0;
for (int i = 0; i < 16; ++i)
send(0x7B << 8 | 0xB0 | i);
_timer_proc = 0;
}
if (isOpen()) {
for (int i = 0; i < 16; ++i)
send(0x7B << 8 | 0xB0 | i);
}
}
uint32 MidiDriver_MPU401::property(int prop, uint32 param) {

View File

@ -26,7 +26,7 @@
#ifndef SOUND_MPU401_H
#define SOUND_MPU401_H
#include "sound/mididrv.h"
#include "audio/mididrv.h"
////////////////////////////////////////
//
@ -46,22 +46,22 @@ private:
public:
MidiDriver *device();
byte getNumber() { return _channel; }
void release() { _allocated = false; }
virtual void release() { _allocated = false; }
void send(uint32 b);
virtual void send(uint32 b);
// Regular messages
void noteOff(byte note);
void noteOn(byte note, byte velocity);
void programChange(byte program);
void pitchBend(int16 bend);
virtual void noteOff(byte note);
virtual void noteOn(byte note, byte velocity);
virtual void programChange(byte program);
virtual void pitchBend(int16 bend);
// Control Change messages
void controlChange(byte control, byte value);
void pitchBendFactor(byte value);
virtual void controlChange(byte control, byte value);
virtual void pitchBendFactor(byte value);
// SysEx messages
void sysEx_customInstrument(uint32 type, const byte *instr);
virtual void sysEx_customInstrument(uint32 type, const byte *instr);
// Only to be called by the owner
void init(MidiDriver *owner, byte channel);
@ -78,14 +78,15 @@ private:
public:
MidiDriver_MPU401();
virtual ~MidiDriver_MPU401();
virtual void close();
void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
uint32 getBaseTempo(void) { return 10000; }
uint32 property(int prop, uint32 param);
virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
virtual uint32 getBaseTempo(void) { return 10000; }
virtual uint32 property(int prop, uint32 param);
MidiChannel *allocateChannel();
MidiChannel *getPercussionChannel() { return &_midi_channels[9]; }
virtual MidiChannel *allocateChannel();
virtual MidiChannel *getPercussionChannel() { return &_midi_channels[9]; }
};

View File

@ -23,7 +23,7 @@
*
*/
#include "sound/musicplugin.h"
#include "audio/musicplugin.h"
#include "common/hash-str.h"
#include "common/translation.h"

View File

@ -26,7 +26,7 @@
#define SOUND_MUSICPLUGIN_H
#include "base/plugins.h"
#include "sound/mididrv.h"
#include "audio/mididrv.h"
#include "common/list.h"
class MusicPluginObject;

View File

@ -22,7 +22,7 @@
* $Id$
*/
#include "sound/null.h"
#include "audio/null.h"
Common::Error NullMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_NULL();

View File

@ -25,14 +25,15 @@
#ifndef SOUND_NULL_H
#define SOUND_NULL_H
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include "common/translation.h"
/* NULL driver */
class MidiDriver_NULL : public MidiDriver_MPU401 {
public:
int open() { return 0; }
bool isOpen() const { return true; }
void send(uint32 b) { }
};

View File

@ -31,9 +31,9 @@
* improvements over the original code were made.
*/
#include "sound/audiostream.h"
#include "sound/rate.h"
#include "sound/mixer.h"
#include "audio/audiostream.h"
#include "audio/rate.h"
#include "audio/mixer.h"
#include "common/frac.h"
#include "common/util.h"

View File

@ -44,9 +44,9 @@
* other improvments over the original code were made.
*/
#include "sound/audiostream.h"
#include "sound/rate.h"
#include "sound/mixer.h"
#include "audio/audiostream.h"
#include "audio/rate.h"
#include "audio/mixer.h"
#include "common/util.h"
//#define DEBUG_RATECONV
@ -60,7 +60,7 @@ namespace Audio {
* ARM routine we call doesn't respect those definitions.
*/
#define FRAC_BITS 16
#define FRAC_ONE (1<<FRAC_BITS)
#define FRAC_ONE (1 << FRAC_BITS)
/**
* The size of the intermediate input cache. Bigger values may increase
@ -138,68 +138,66 @@ extern "C" {
}
extern "C" st_sample_t *ARM_SimpleRate_M(
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
SimpleRateDetails *sr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
SimpleRateDetails *sr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
extern "C" st_sample_t *ARM_SimpleRate_S(
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
SimpleRateDetails *sr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
SimpleRateDetails *sr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
extern "C" st_sample_t *ARM_SimpleRate_R(
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
SimpleRateDetails *sr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
SimpleRateDetails *sr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
extern "C" int SimpleRate_readFudge(Audio::AudioStream &input,
int16 *a, int b)
extern "C" int SimpleRate_readFudge(Audio::AudioStream &input, int16 *a, int b)
{
#ifdef DEBUG_RATECONV
fprintf(stderr, "Reading ptr=%x n%d\n", a, b);
fflush(stderr);
debug("Reading ptr=%x n%d", a, b);
#endif
return input.readBuffer(a, b);
return input.readBuffer(a, b);
}
template<bool stereo, bool reverseStereo>
int SimpleRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
#ifdef DEBUG_RATECONV
fprintf(stderr, "Simple st=%d rev=%d\n", stereo, reverseStereo);
fflush(stderr);
debug("Simple st=%d rev=%d", stereo, reverseStereo);
#endif
st_sample_t *ostart = obuf;
if (!stereo) {
obuf = ARM_SimpleRate_M(input,
&SimpleRate_readFudge,
&sr,
obuf, osamp, vol_l, vol_r);
&SimpleRate_readFudge,
&sr,
obuf, osamp, vol_l, vol_r);
} else if (reverseStereo) {
obuf = ARM_SimpleRate_R(input,
&SimpleRate_readFudge,
&sr,
obuf, osamp, vol_l, vol_r);
&SimpleRate_readFudge,
&sr,
obuf, osamp, vol_l, vol_r);
} else {
obuf = ARM_SimpleRate_S(input,
&SimpleRate_readFudge,
&sr,
obuf, osamp, vol_l, vol_r);
&SimpleRate_readFudge,
&sr,
obuf, osamp, vol_l, vol_r);
}
return (obuf-ostart)/2;
return (obuf - ostart) / 2;
}
/**
@ -242,31 +240,31 @@ extern "C" {
}
extern "C" st_sample_t *ARM_LinearRate_M(
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
LinearRateDetails *lr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
LinearRateDetails *lr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
extern "C" st_sample_t *ARM_LinearRate_S(
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
LinearRateDetails *lr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
LinearRateDetails *lr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
extern "C" st_sample_t *ARM_LinearRate_R(
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
LinearRateDetails *lr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
AudioStream &input,
int (*fn)(Audio::AudioStream&,int16*,int),
LinearRateDetails *lr,
st_sample_t *obuf,
st_size_t osamp,
st_volume_t vol_l,
st_volume_t vol_r);
template<bool stereo, bool reverseStereo>
class LinearRateConverter : public RateConverter {
@ -318,28 +316,33 @@ template<bool stereo, bool reverseStereo>
int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
#ifdef DEBUG_RATECONV
fprintf(stderr, "Linear st=%d rev=%d\n", stereo, reverseStereo);
fflush(stderr);
debug("Linear st=%d rev=%d", stereo, reverseStereo);
#endif
st_sample_t *ostart = obuf;
if (vol_l > 0xff)
vol_l = 0xff;
if (vol_r > 0xff)
vol_r = 0xff;
if (!stereo) {
obuf = ARM_LinearRate_M(input,
&SimpleRate_readFudge,
&lr,
obuf, osamp, vol_l, vol_r);
&SimpleRate_readFudge,
&lr,
obuf, osamp, vol_l, vol_r);
} else if (reverseStereo) {
obuf = ARM_LinearRate_R(input,
&SimpleRate_readFudge,
&lr,
obuf, osamp, vol_l, vol_r);
&SimpleRate_readFudge,
&lr,
obuf, osamp, vol_l, vol_r);
} else {
obuf = ARM_LinearRate_S(input,
&SimpleRate_readFudge,
&lr,
obuf, osamp, vol_l, vol_r);
&SimpleRate_readFudge,
&lr,
obuf, osamp, vol_l, vol_r);
}
return (obuf-ostart)/2;
return (obuf - ostart) / 2;
}
@ -358,31 +361,32 @@ extern "C" {
}
extern "C" st_sample_t *ARM_CopyRate_M(
st_size_t len,
st_sample_t *obuf,
st_volume_t vol_l,
st_volume_t vol_r,
st_sample_t *_buffer);
st_size_t len,
st_sample_t *obuf,
st_volume_t vol_l,
st_volume_t vol_r,
st_sample_t *_buffer);
extern "C" st_sample_t *ARM_CopyRate_S(
st_size_t len,
st_sample_t *obuf,
st_volume_t vol_l,
st_volume_t vol_r,
st_sample_t *_buffer);
st_size_t len,
st_sample_t *obuf,
st_volume_t vol_l,
st_volume_t vol_r,
st_sample_t *_buffer);
extern "C" st_sample_t *ARM_CopyRate_R(
st_size_t len,
st_sample_t *obuf,
st_volume_t vol_l,
st_volume_t vol_r,
st_sample_t *_buffer);
st_size_t len,
st_sample_t *obuf,
st_volume_t vol_l,
st_volume_t vol_r,
st_sample_t *_buffer);
template<bool stereo, bool reverseStereo>
class CopyRateConverter : public RateConverter {
st_sample_t *_buffer;
st_size_t _bufferSize;
public:
CopyRateConverter() : _buffer(0), _bufferSize(0) {}
~CopyRateConverter() {
@ -393,11 +397,10 @@ public:
assert(input.isStereo() == stereo);
#ifdef DEBUG_RATECONV
fprintf(stderr, "Copy st=%d rev=%d\n", stereo, reverseStereo);
fflush(stderr);
debug("Copy st=%d rev=%d", stereo, reverseStereo);
#endif
st_size_t len;
st_sample_t *ostart = obuf;
st_sample_t *ostart = obuf;
if (stereo)
osamp *= 2;
@ -422,8 +425,9 @@ fflush(stderr);
else
obuf = ARM_CopyRate_M(len, obuf, vol_l, vol_r, _buffer);
return (obuf-ostart)/2;
return (obuf - ostart) / 2;
}
virtual int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) {
return (ST_SUCCESS);
}
@ -467,3 +471,5 @@ RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stere
}
} // End of namespace Audio

View File

@ -1,3 +1,4 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
@ -22,11 +23,11 @@
* $Id$
*/
#include "sound/softsynth/emumidi.h"
#include "audio/softsynth/emumidi.h"
#include "common/debug.h"
#include "common/util.h"
#include "sound/fmopl.h"
#include "sound/musicplugin.h"
#include "audio/fmopl.h"
#include "audio/musicplugin.h"
#include "common/translation.h"
#ifdef DEBUG_ADLIB
@ -118,7 +119,7 @@ public:
byte getNumber() { return _channel; }
void release() { _allocated = false; }
void send (uint32 b);
void send(uint32 b);
// Regular messages
void noteOff(byte note);

View File

@ -23,7 +23,7 @@
*
*/
#include "sound/null.h"
#include "audio/null.h"
// Plugin interface
// (This can only create a null driver since apple II gs support seeems not to be implemented

View File

@ -22,8 +22,8 @@
* $Id$
*/
#include "sound/softsynth/cms.h"
#include "sound/null.h"
#include "audio/softsynth/cms.h"
#include "audio/null.h"
#include "common/textconsole.h"
#include "common/translation.h"
@ -86,35 +86,39 @@ static const int amplitude_lookup[16] = {
void CMSEmulator::portWrite(int port, int val) {
switch (port) {
case 0x220:
portWriteIntern(0, 1, val);
break;
case 0x220:
portWriteIntern(0, 1, val);
break;
case 0x221:
_saa1099[0].selected_reg = val & 0x1f;
if (_saa1099[0].selected_reg == 0x18 || _saa1099[0].selected_reg == 0x19) {
/* clock the envelope channels */
if (_saa1099[0].env_clock[0]) envelope(0, 0);
if (_saa1099[0].env_clock[1]) envelope(0, 1);
}
break;
case 0x221:
_saa1099[0].selected_reg = val & 0x1f;
if (_saa1099[0].selected_reg == 0x18 || _saa1099[0].selected_reg == 0x19) {
/* clock the envelope channels */
if (_saa1099[0].env_clock[0])
envelope(0, 0);
if (_saa1099[0].env_clock[1])
envelope(0, 1);
}
break;
case 0x222:
portWriteIntern(1, 1, val);
break;
case 0x222:
portWriteIntern(1, 1, val);
break;
case 0x223:
_saa1099[1].selected_reg = val & 0x1f;
if (_saa1099[1].selected_reg == 0x18 || _saa1099[1].selected_reg == 0x19) {
/* clock the envelope channels */
if (_saa1099[1].env_clock[0]) envelope(1, 0);
if (_saa1099[1].env_clock[1]) envelope(1, 1);
}
break;
case 0x223:
_saa1099[1].selected_reg = val & 0x1f;
if (_saa1099[1].selected_reg == 0x18 || _saa1099[1].selected_reg == 0x19) {
/* clock the envelope channels */
if (_saa1099[1].env_clock[0])
envelope(1, 0);
if (_saa1099[1].env_clock[1])
envelope(1, 1);
}
break;
default:
warning("CMSEmulator got port: 0x%X", port);
break;
default:
warning("CMSEmulator got port: 0x%X", port);
break;
}
}
@ -177,10 +181,10 @@ void CMSEmulator::update(int chip, int16 *buffer, int length) {
for (ch = 0; ch < 2; ch++) {
switch (saa->noise_params[ch]) {
case 0: saa->noise[ch].freq = 31250.0 * 2; break;
case 1: saa->noise[ch].freq = 15625.0 * 2; break;
case 2: saa->noise[ch].freq = 7812.5 * 2; break;
case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break;
case 0: saa->noise[ch].freq = 31250.0 * 2; break;
case 1: saa->noise[ch].freq = 15625.0 * 2; break;
case 2: saa->noise[ch].freq = 7812.5 * 2; break;
case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break;
}
}
@ -254,95 +258,95 @@ void CMSEmulator::portWriteIntern(int chip, int offset, int data) {
int ch;
switch (reg) {
/* channel i amplitude */
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
ch = reg & 7;
saa->channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f];
saa->channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f];
break;
/* channel i amplitude */
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
ch = reg & 7;
saa->channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f];
saa->channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f];
break;
/* channel i frequency */
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
ch = reg & 7;
saa->channels[ch].frequency = data & 0xff;
break;
/* channel i frequency */
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
ch = reg & 7;
saa->channels[ch].frequency = data & 0xff;
break;
/* channel i octave */
case 0x10:
case 0x11:
case 0x12:
ch = (reg - 0x10) << 1;
saa->channels[ch + 0].octave = data & 0x07;
saa->channels[ch + 1].octave = (data >> 4) & 0x07;
break;
/* channel i octave */
case 0x10:
case 0x11:
case 0x12:
ch = (reg - 0x10) << 1;
saa->channels[ch + 0].octave = data & 0x07;
saa->channels[ch + 1].octave = (data >> 4) & 0x07;
break;
/* channel i frequency enable */
case 0x14:
saa->channels[0].freq_enable = data & 0x01;
saa->channels[1].freq_enable = data & 0x02;
saa->channels[2].freq_enable = data & 0x04;
saa->channels[3].freq_enable = data & 0x08;
saa->channels[4].freq_enable = data & 0x10;
saa->channels[5].freq_enable = data & 0x20;
break;
/* channel i frequency enable */
case 0x14:
saa->channels[0].freq_enable = data & 0x01;
saa->channels[1].freq_enable = data & 0x02;
saa->channels[2].freq_enable = data & 0x04;
saa->channels[3].freq_enable = data & 0x08;
saa->channels[4].freq_enable = data & 0x10;
saa->channels[5].freq_enable = data & 0x20;
break;
/* channel i noise enable */
case 0x15:
saa->channels[0].noise_enable = data & 0x01;
saa->channels[1].noise_enable = data & 0x02;
saa->channels[2].noise_enable = data & 0x04;
saa->channels[3].noise_enable = data & 0x08;
saa->channels[4].noise_enable = data & 0x10;
saa->channels[5].noise_enable = data & 0x20;
break;
/* channel i noise enable */
case 0x15:
saa->channels[0].noise_enable = data & 0x01;
saa->channels[1].noise_enable = data & 0x02;
saa->channels[2].noise_enable = data & 0x04;
saa->channels[3].noise_enable = data & 0x08;
saa->channels[4].noise_enable = data & 0x10;
saa->channels[5].noise_enable = data & 0x20;
break;
/* noise generators parameters */
case 0x16:
saa->noise_params[0] = data & 0x03;
saa->noise_params[1] = (data >> 4) & 0x03;
break;
/* noise generators parameters */
case 0x16:
saa->noise_params[0] = data & 0x03;
saa->noise_params[1] = (data >> 4) & 0x03;
break;
/* envelope generators parameters */
case 0x18:
case 0x19:
ch = reg - 0x18;
saa->env_reverse_right[ch] = data & 0x01;
saa->env_mode[ch] = (data >> 1) & 0x07;
saa->env_bits[ch] = data & 0x10;
saa->env_clock[ch] = data & 0x20;
saa->env_enable[ch] = data & 0x80;
/* reset the envelope */
saa->env_step[ch] = 0;
break;
/* envelope generators parameters */
case 0x18:
case 0x19:
ch = reg - 0x18;
saa->env_reverse_right[ch] = data & 0x01;
saa->env_mode[ch] = (data >> 1) & 0x07;
saa->env_bits[ch] = data & 0x10;
saa->env_clock[ch] = data & 0x20;
saa->env_enable[ch] = data & 0x80;
/* reset the envelope */
saa->env_step[ch] = 0;
break;
/* channels enable & reset generators */
case 0x1c:
saa->all_ch_enable = data & 0x01;
saa->sync_state = data & 0x02;
if (data & 0x02) {
int i;
/* Synch & Reset generators */
for (i = 0; i < 6; i++) {
saa->channels[i].level = 0;
saa->channels[i].counter = 0.0;
}
/* channels enable & reset generators */
case 0x1c:
saa->all_ch_enable = data & 0x01;
saa->sync_state = data & 0x02;
if (data & 0x02) {
int i;
/* Synch & Reset generators */
for (i = 0; i < 6; i++) {
saa->channels[i].level = 0;
saa->channels[i].counter = 0.0;
}
break;
}
break;
default:
// The CMS allows all registers to be written, so we just output some debug
// message here
debug(5, "CMS Unkown write to reg %x with %x",reg, data);
default:
// The CMS allows all registers to be written, so we just output some debug
// message here
debug(5, "CMS Unknown write to reg %x with %x",reg, data);
}
}

View File

@ -25,9 +25,9 @@
#ifndef SOUND_SOFTSYNTH_EMUMIDI_H
#define SOUND_SOFTSYNTH_EMUMIDI_H
#include "sound/audiostream.h"
#include "sound/mididrv.h"
#include "sound/mixer.h"
#include "audio/audiostream.h"
#include "audio/mididrv.h"
#include "audio/mixer.h"
#define FIXP_SHIFT 16
@ -45,25 +45,24 @@ private:
int _samplesPerTick;
protected:
int _baseFreq;
virtual void generateSamples(int16 *buf, int len) = 0;
virtual void onTimer() {}
int _baseFreq;
public:
MidiDriver_Emulated(Audio::Mixer *mixer) : _mixer(mixer) {
_isOpen = false;
_timerProc = 0;
_timerParam = 0;
_nextTick = 0;
_samplesPerTick = 0;
_baseFreq = 250;
MidiDriver_Emulated(Audio::Mixer *mixer) :
_mixer(mixer),
_isOpen(false),
_timerProc(0),
_timerParam(0),
_nextTick(0),
_samplesPerTick(0),
_baseFreq(250) {
}
int open() {
// MidiDriver API
virtual int open() {
_isOpen = true;
int d = getRate() / _baseFreq;
@ -73,19 +72,23 @@ public:
// but less prone to arithmetic overflow.
_samplesPerTick = (d << FIXP_SHIFT) + (r << FIXP_SHIFT) / _baseFreq;
return 0;
}
void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
bool isOpen() const { return _isOpen; }
virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
_timerProc = timer_proc;
_timerParam = timer_param;
}
uint32 getBaseTempo() { return 1000000 / _baseFreq; }
virtual uint32 getBaseTempo() {
return 1000000 / _baseFreq;
}
// AudioStream API
int readBuffer(int16 *data, const int numSamples) {
virtual int readBuffer(int16 *data, const int numSamples) {
const int stereoFactor = isStereo() ? 2 : 1;
int len = numSamples / stereoFactor;
int step;
@ -101,16 +104,22 @@ public:
if (!(_nextTick >> FIXP_SHIFT)) {
if (_timerProc)
(*_timerProc)(_timerParam);
onTimer();
_nextTick += _samplesPerTick;
}
data += step * stereoFactor;
len -= step;
} while (len);
return numSamples;
}
bool endOfData() const { return false; }
virtual bool endOfData() const {
return false;
}
};
#endif

View File

@ -27,9 +27,9 @@
#ifdef USE_FLUIDSYNTH
#include "common/config-manager.h"
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "sound/softsynth/emumidi.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include "audio/softsynth/emumidi.h"
#include <fluidsynth.h>
@ -40,7 +40,6 @@ private:
fluid_synth_t *_synth;
int _soundFont;
int _outputRate;
Audio::SoundHandle _handle;
protected:
// Because GCC complains about casting from const to non-const...
@ -144,7 +143,7 @@ int MidiDriver_FluidSynth::open() {
MidiDriver_Emulated::open();
// The MT-32 emulator uses kSFXSoundType here. I don't know why.
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
@ -153,7 +152,7 @@ void MidiDriver_FluidSynth::close() {
return;
_isOpen = false;
_mixer->stopHandle(_handle);
_mixer->stopHandle(_mixerSoundHandle);
if (_soundFont != -1)
fluid_synth_sfunload(_synth, _soundFont, 1);

View File

@ -26,11 +26,11 @@
#ifdef USE_MT32EMU
#include "sound/softsynth/mt32/mt32emu.h"
#include "audio/softsynth/mt32/mt32emu.h"
#include "sound/softsynth/emumidi.h"
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "audio/softsynth/emumidi.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include "common/config-manager.h"
#include "common/debug.h"
@ -51,7 +51,6 @@ class MidiChannel_MT32 : public MidiChannel_MPU401 {
class MidiDriver_MT32 : public MidiDriver_Emulated {
private:
Audio::SoundHandle _handle;
MidiChannel_MT32 _midiChannels[16];
uint16 _channelMask;
MT32Emu::Synth *_synth;
@ -149,7 +148,7 @@ static void drawProgress(float progress) {
Common::Rect r(x, y, x + w, y + h);
uint32 col;
if (screenFormat.bytesPerPixel > 1)
col = screenFormat.RGBToColor(0, 171, 0);
else
@ -230,8 +229,7 @@ static void MT32_PrintDebug(void *userData, const char *fmt, va_list list) {
static int MT32_Report(void *userData, MT32Emu::ReportType type, const void *reportData) {
switch (type) {
case MT32Emu::ReportType_lcdMessage:
// FIXME implament in Residual
// g_system->displayMessageOnOSD((const char *)reportData);
g_system->displayMessageOnOSD((const char *)reportData);
break;
case MT32Emu::ReportType_errorControlROM:
error("Failed to load MT32_CONTROL.ROM");
@ -317,9 +315,9 @@ int MidiDriver_MT32::open() {
if (screenFormat.bytesPerPixel == 1) {
const byte dummy_palette[] = {
0, 0, 0, 0, // background
0, 171, 0, 0, // border, font
171, 0, 0, 0 // fill
0, 0, 0, // background
0, 171, 0, // border, font
171, 0, 0 // fill
};
// TODO implement in Residual
@ -340,7 +338,7 @@ int MidiDriver_MT32::open() {
g_system->updateScreen();*/
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
@ -382,7 +380,7 @@ void MidiDriver_MT32::close() {
// Detach the player callback handler
setTimerCallback(NULL, NULL);
// Detach the mixer callback handler
_mixer->stopHandle(_handle);
_mixer->stopHandle(_mixerSoundHandle);
_synth->close();
delete _synth;

View File

@ -29,7 +29,7 @@
// http://www.dreampoint.co.uk
// This code is public domain
#include "sound/softsynth/mt32/freeverb.h"
#include "audio/softsynth/mt32/freeverb.h"
comb::comb() {
filterstore = 0;
@ -125,12 +125,12 @@ revmodel::revmodel() {
allpassR[2].setfeedback(0.5f);
allpassL[3].setfeedback(0.5f);
allpassR[3].setfeedback(0.5f);
setmode(initialmode);
setwet(initialwet);
setroomsize(initialroom);
setdry(initialdry);
setdamp(initialdamp);
setwidth(initialwidth);
setmode(initialmode);
// Buffer will be full of rubbish - so we MUST mute them
mute();

View File

@ -1,4 +1,4 @@
MODULE := sound/softsynth/mt32
MODULE := audio/softsynth/mt32
MODULE_OBJS := \
mt32_file.o \

View File

@ -0,0 +1,70 @@
/* Copyright (c) 2003-2005 Various contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "mt32emu.h"
namespace MT32Emu {
bool File::readBit16u(Bit16u *in) {
Bit8u b[2];
if (read(&b[0], 2) != 2)
return false;
*in = ((b[0] << 8) | b[1]);
return true;
}
bool File::readBit32u(Bit32u *in) {
Bit8u b[4];
if (read(&b[0], 4) != 4)
return false;
*in = ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]);
return true;
}
bool File::writeBit16u(Bit16u out) {
if (!writeBit8u((Bit8u)((out & 0xFF00) >> 8))) {
return false;
}
if (!writeBit8u((Bit8u)(out & 0x00FF))) {
return false;
}
return true;
}
bool File::writeBit32u(Bit32u out) {
if (!writeBit8u((Bit8u)((out & 0xFF000000) >> 24))) {
return false;
}
if (!writeBit8u((Bit8u)((out & 0x00FF0000) >> 16))) {
return false;
}
if (!writeBit8u((Bit8u)((out & 0x0000FF00) >> 8))) {
return false;
}
if (!writeBit8u((Bit8u)(out & 0x000000FF))) {
return false;
}
return true;
}
} // End of namespace MT32Emu

View File

@ -22,7 +22,7 @@
#ifndef MT32EMU_FILE_H
#define MT32EMU_FILE_H
#include <stdio.h>
#include "common/sys.h"
namespace MT32Emu {
@ -47,19 +47,6 @@ public:
virtual bool isEOF() = 0;
};
class ANSIFile: public File {
private:
FILE *fp;
public:
bool open(const char *filename, OpenMode mode);
void close();
size_t read(void *in, size_t size);
bool readBit8u(Bit8u *in);
size_t write(const void *out, size_t size);
bool writeBit8u(Bit8u out);
bool isEOF();
};
}
} // End of namespace MT32Emu
#endif

View File

@ -283,6 +283,7 @@ void Part::cacheTimbre(PatchCache cache[4], const TimbreParam *timbre) {
backupCacheToPartials(cache);
int partialCount = 0;
for (int t = 0; t < 4; t++) {
cache[t].PCMPartial = false;
if (((timbre->common.pmute >> t) & 0x1) == 1) {
cache[t].playPartial = true;
partialCount++;

View File

@ -118,7 +118,7 @@ void Partial::initKeyFollow(int key) {
#endif
#if MT32EMU_ACCURATENOTES == 1
noteVal = newPitch;
synth->printDebug("key=%d, pitch=%f, pitchKeyfollow=%f, pitchShift=%f, newPitch=%f", key, patchCache->pitch, patchCache->pitchKeyfollow, patchCache->pitchShift, newPitch);
synth->printDebug("key=%d, pitch=%f, pitchKeyfollow=%f, pitchShift=%f, newPitch=%f", key, (double)patchCache->pitch, (double)patchCache->pitchKeyfollow, (double)patchCache->pitchShift, (double)newPitch);
#else
float newPitchInt;
float newPitchFract = modff(newPitch, &newPitchInt);
@ -128,7 +128,7 @@ void Partial::initKeyFollow(int key) {
}
noteVal = (int)newPitchInt;
fineShift = (int)(powf(2.0f, newPitchFract / 12.0f) * 4096.0f);
synth->printDebug("key=%d, pitch=%f, pitchKeyfollow=%f, pitchShift=%f, newPitch=%f, noteVal=%d, fineShift=%d", key, patchCache->pitch, patchCache->pitchKeyfollow, patchCache->pitchShift, newPitch, noteVal, fineShift);
synth->printDebug("key=%d, pitch=%f, pitchKeyfollow=%f, pitchShift=%f, newPitch=%f, noteVal=%d, fineShift=%d", key, (double)patchCache->pitch, (double)patchCache->pitchKeyfollow, (double)patchCache->pitchShift, (double)newPitch, noteVal, fineShift);
#endif
// FIXME:KG: Raise/lower by octaves until in the supported range.
while (noteVal > HIGHEST_NOTE) // FIXME:KG: see tables.cpp: >108?
@ -451,7 +451,7 @@ void Partial::setBend(float factor) {
// FIXME:KG: Bend should be influenced by pitch key-follow too, according to docs.
float bendSemitones = factor * patchCache->benderRange; // -24 .. 24
float mult = powf(2.0f, bendSemitones / 12.0f);
synth->printDebug("setBend(): factor=%f, benderRange=%f, semitones=%f, mult=%f\n", factor, patchCache->benderRange, bendSemitones, mult);
synth->printDebug("setBend(): factor=%f, benderRange=%f, semitones=%f, mult=%f\n", (double)factor, (double)patchCache->benderRange, (double)bendSemitones, (double)mult);
bendShift = (int)(mult * 4096.0f);
}

View File

@ -162,21 +162,11 @@ void Synth::initReverb(Bit8u newRevMode, Bit8u newRevTime, Bit8u newRevLevel) {
}
File *Synth::openFile(const char *filename, File::OpenMode mode) {
if (myProp.openFile != NULL) {
return myProp.openFile(myProp.userData, filename, mode);
}
char pathBuf[2048];
if (myProp.baseDir != NULL) {
strcpy(&pathBuf[0], myProp.baseDir);
strcat(&pathBuf[0], filename);
filename = pathBuf;
}
ANSIFile *file = new ANSIFile();
if (!file->open(filename, mode)) {
delete file;
return NULL;
}
return file;
// It should never happen that openFile is NULL in our use case.
// Just to cover the case where something is horrible wrong we
// use an assert here.
assert(myProp.openFile != NULL);
return myProp.openFile(myProp.userData, filename, mode);
}
void Synth::closeFile(File *file) {
@ -326,7 +316,7 @@ bool Synth::initPCMList(Bit16u mapAddress, Bit16u count) {
// The number below is confirmed to a reasonable degree of accuracy on CM-32L
double STANDARDFREQ = 442.0;
float rTune = (float)(STANDARDFREQ * pow(2.0, (0x5000 - rTuneOffset) / 4056.0 - 9.0 / 12.0));
//printDebug("%f,%d,%d", pTune, tps[i].pitchCoarse, tps[i].pitchFine);
//printDebug("%f,%d,%d", (double)pTune, tps[i].pitchCoarse, tps[i].pitchFine);
if (rAddr + rLen > pcmROMSize) {
printDebug("Control ROM error: Wave map entry %d points to invalid PCM address 0x%04X, length 0x%04X", i, rAddr, rLen);
return false;
@ -347,7 +337,8 @@ bool Synth::initRhythmTimbre(int timbreNum, const Bit8u *mem, unsigned int memLe
memcpy(&timbre->common, mem, 14);
unsigned int memPos = 14;
char drumname[11];
Common::strlcpy(drumname, timbre->common.name, 11);
memset(drumname, 0, 11);
memcpy(drumname, timbre->common.name, 10);
for (int t = 0; t < 4; t++) {
if (((timbre->common.pmute >> t) & 0x1) == 0x1) {
if (memPos + 58 >= memLen) {
@ -1030,7 +1021,7 @@ bool Synth::refreshSystem() {
// The LAPC-I documentation claims a range of 427.5Hz-452.6Hz (similar to what we have here)
// The MT-32 documentation claims a range of 432.1Hz-457.6Hz
masterTune = 440.0f * powf(2.0f, (mt32ram.system.masterTune - 64.0f) / (128.0f * 12.0f));
printDebug(" Master Tune: %f", masterTune);
printDebug(" Master Tune: %f", (double)masterTune);
printDebug(" Reverb: mode=%d, time=%d, level=%d", mt32ram.system.reverbMode, mt32ram.system.reverbTime, mt32ram.system.reverbLevel);
report(ReportType_newReverbMode, &mt32ram.system.reverbMode);
report(ReportType_newReverbTime, &mt32ram.system.reverbTime);

View File

@ -329,7 +329,7 @@ void Tables::initMT32ConstantTables(Synth *synth) {
tdist = (lf - 25.0f) / 25.0f;
padjtable[lf] = 1.0f - tdist;
}
//synth->printDebug("lf %d = padj %f", lf, padjtable[lf]);
//synth->printDebug("lf %d = padj %f", lf, (double)padjtable[lf]);
}
float lfp, depf, finalval, tlf;
@ -352,7 +352,7 @@ void Tables::initMT32ConstantTables(Synth *synth) {
pval = (int)finalval;
pitchEnvVal[lf][depat] = pval;
//synth->printDebug("lf %d depat %d pval %d tlf %f lfp %f", lf,depat,pval, tlf, lfp);
//synth->printDebug("lf %d depat %d pval %d tlf %f lfp %f", lf,depat,pval, (double)tlf, (double)lfp);
} else {
pitchEnvVal[lf][depat] = 4096;
//synth->printDebug("lf %d depat %d pval 4096", lf, depat);
@ -402,7 +402,7 @@ void Tables::initMT32ConstantTables(Synth *synth) {
tvaBiasMult[lf][distval] = (int)(dval * 256.0f);
}
}
//synth->printDebug("Ampbias lf %d distval %d = %f (%x) %f", lf, distval, dval, tvaBiasMult[lf][distval],amplog);
//synth->printDebug("Ampbias lf %d distval %d = %f (%x) %f", lf, distval, (double)dval, tvaBiasMult[lf][distval],(double)amplog);
}
}
@ -430,7 +430,7 @@ void Tables::initMT32ConstantTables(Synth *synth) {
tvfBiasMult[lf][distval] = (int)(dval * 256.0f);
}
}
//synth->printDebug("Fbias lf %d distval %d = %f (%x) %f", lf, distval, dval, tvfBiasMult[lf][distval],amplog);
//synth->printDebug("Fbias lf %d distval %d = %f (%x) %f", lf, distval, (double)dval, tvfBiasMult[lf][distval],(double)amplog);
}
}
}
@ -471,7 +471,7 @@ static void initDep(KeyLookup *keyLookup, float f) {
keyLookup->envTimeMult[dep] = (int)(ff * 256.0f);
}
}
//synth->printDebug("F %f d1 %x d2 %x d3 %x d4 %x d5 %x", f, noteLookup->fildepTable[0], noteLookup->fildepTable[1], noteLookup->fildepTable[2], noteLookup->fildepTable[3], noteLookup->fildepTable[4]);
//synth->printDebug("F %f d1 %x d2 %x d3 %x d4 %x d5 %x", (double)f, noteLookup->fildepTable[0], noteLookup->fildepTable[1], noteLookup->fildepTable[2], noteLookup->fildepTable[3], noteLookup->fildepTable[4]);
}
Bit16s Tables::clampWF(Synth *synth, const char *n, float ampVal, double input) {
@ -586,8 +586,8 @@ File *Tables::initNote(Synth *synth, NoteLookup *noteLookup, float note, float r
initSaw(noteLookup, noteLookup->div2);
//synth->printDebug("Note %f; freq=%f, div=%f", note, freq, rate / freq);
file = initWave(synth, noteLookup, (const float)WGAMP, div2, file);
//synth->printDebug("Note %f; freq=%f, div=%f", (double)note, (double)freq, (double) rate / freq);
file = initWave(synth, noteLookup, WGAMP, div2, file);
// Create the pitch tables
if (noteLookup->wavTable == NULL)
@ -730,7 +730,7 @@ Tables::Tables() {
bool Tables::init(Synth *synth, PCMWaveEntry *pcmWaves, float sampleRate, float masterTune) {
if (sampleRate <= 0.0f) {
synth->printDebug("Bad sampleRate (%f <= 0.0f)", sampleRate);
synth->printDebug("Bad sampleRate (%f <= 0.0f)", (double)sampleRate);
return false;
}
if (initialisedSampleRate == 0.0f) {

View File

@ -41,10 +41,6 @@
namespace OPL {
namespace DOSBox {
#ifndef PI
#define PI 3.14159265358979323846
#endif
namespace DBOPL {
#define OPLRATE ((double)(14318180.0 / 288.0))
@ -224,7 +220,7 @@ static inline Bits MakeVolume( Bitu wave, Bitu volume ) {
}
#endif
return (sig >> exp);
};
}
static Bits DB_FASTCALL WaveForm0( Bitu i, Bitu volume ) {
Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
@ -418,7 +414,7 @@ Bits Operator::TemplateVolume( ) {
}
//In sustain phase, but not sustaining, do regular release
case RELEASE:
vol += RateForward( releaseAdd );;
vol += RateForward( releaseAdd );
if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
volume = ENV_MAX;
SetState( OFF );
@ -576,7 +572,7 @@ INLINE Bits Operator::GetWave( Bitu index, Bitu vol ) {
return (waveBase[ index & waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH;
#elif ( DBOPL_WAVE == WAVE_TABLELOG )
Bit32s wave = waveBase[ index & waveMask ];
Bit32u total = ( wave & 0x7fff ) + vol << ( 3 - ENV_EXTRA );
Bit32u total = ( wave & 0x7fff ) + ( vol << ( 3 - ENV_EXTRA ) );
Bit32s sig = ExpTable[ total & 0xff ];
Bit32u exp = total >> 8;
Bit32s neg = wave >> 16;
@ -1392,7 +1388,7 @@ void InitTables( void ) {
//Add 0.5 for the trunc rounding of the integer cast
//Do a PI sinetable instead of the original 0.5 PI
for ( int i = 0; i < 512; i++ ) {
SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (M_PI / 512.0) ) ) / log10(2.0)*256 );
}
#endif
#if ( DBOPL_WAVE == WAVE_TABLEMUL )
@ -1406,7 +1402,7 @@ void InitTables( void ) {
//Sine Wave Base
for ( int i = 0; i < 512; i++ ) {
WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084);
WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (M_PI / 512.0) ) * 4084);
WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
}
//Exponential wave
@ -1418,7 +1414,7 @@ void InitTables( void ) {
#if ( DBOPL_WAVE == WAVE_TABLELOG )
//Sine Wave Base
for ( int i = 0; i < 512; i++ ) {
WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (M_PI / 512.0) ) ) / log10(2.0)*256 );
WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i];
}
//Exponential wave

View File

@ -34,7 +34,7 @@
#ifndef DISABLE_DOSBOX_OPL
#include "sound/fmopl.h"
#include "audio/fmopl.h"
namespace OPL {
namespace DOSBox {

View File

@ -694,7 +694,7 @@ static int OPLOpenTable(void) {
return 0;
}
/* make total level table */
for (t = 0; t < EG_ENT - 1 ; t++) {
for (t = 0; t < EG_ENT - 1; t++) {
rate = ((1 << TL_BITS) - 1) / pow(10.0, EG_STEP * t / 20); /* dB -> voltage */
TL_TABLE[ t] = (int)rate;
TL_TABLE[TL_MAX + t] = -TL_TABLE[t];
@ -708,7 +708,7 @@ static int OPLOpenTable(void) {
/* degree 0 = degree 180 = off */
SIN_TABLE[0] = SIN_TABLE[SIN_ENT /2 ] = &TL_TABLE[EG_ENT - 1];
for (s = 1;s <= SIN_ENT / 4; s++) {
pom = sin(2 * LOCAL_PI * s / SIN_ENT); /* sin */
pom = sin(2 * M_PI * s / SIN_ENT); /* sin */
pom = 20 * log10(1 / pom); /* decibel */
j = int(pom / EG_STEP); /* TL_TABLE steps */
@ -739,14 +739,14 @@ static int OPLOpenTable(void) {
ENV_CURVE[EG_OFF >> ENV_BITS]= EG_ENT - 1;
/* make LFO ams table */
for (i=0; i < AMS_ENT; i++) {
pom = (1.0 + sin(2 * LOCAL_PI * i / AMS_ENT)) / 2; /* sin */
pom = (1.0 + sin(2 * M_PI * i / AMS_ENT)) / 2; /* sin */
AMS_TABLE[i] = (int)((1.0 / EG_STEP) * pom); /* 1dB */
AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */
}
/* make LFO vibrate table */
for (i=0; i < VIB_ENT; i++) {
/* 100cent = 1seminote = 6% ?? */
pom = (double)VIB_RATE * 0.06 * sin(2 * LOCAL_PI * i / VIB_ENT); /* +-100sect step */
pom = (double)VIB_RATE * 0.06 * sin(2 * M_PI * i / VIB_ENT); /* +-100sect step */
VIB_TABLE[i] = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */
VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */
}
@ -1082,10 +1082,10 @@ void OPLResetChip(FM_OPL *OPL) {
for (i = 0xff; i >= 0x20; i--)
OPLWriteReg(OPL,i,0);
/* reset OPerator parameter */
for (c = 0; c < OPL->max_ch ;c++ ) {
for (c = 0; c < OPL->max_ch; c++) {
OPL_CH *CH = &OPL->P_CH[c];
/* OPL->P_CH[c].PAN = OPN_CENTER; */
for (s = 0; s < 2; s++ ) {
for (s = 0; s < 2; s++) {
/* wave table */
CH->SLOT[s].wavetable = &SIN_TABLE[0];
/* CH->SLOT[s].evm = ENV_MOD_RR; */

View File

@ -33,7 +33,7 @@
#include "common/util.h"
#include "common/random.h"
#include "sound/fmopl.h"
#include "audio/fmopl.h"
namespace OPL {
namespace MAME {

View File

@ -23,8 +23,8 @@
*
*/
#include "sound/softsynth/pcspk.h"
#include "sound/null.h"
#include "audio/softsynth/pcspk.h"
#include "audio/null.h"
namespace Audio {
@ -109,7 +109,7 @@ int8 PCSpeaker::generateSine(uint32 x, uint32 oscLength) {
return 0;
// TODO: Maybe using a look-up-table would be better?
return CLIP<int16>((int16) (128 * sin(2.0 * LOCAL_PI * x / oscLength)), -128, 127);
return CLIP<int16>((int16) (128 * sin(2.0 * M_PI * x / oscLength)), -128, 127);
}
int8 PCSpeaker::generateSaw(uint32 x, uint32 oscLength) {

View File

@ -25,8 +25,8 @@
#ifndef SOUND_SOFTSYNTH_PCSPK_H
#define SOUND_SOFTSYNTH_PCSPK_H
#include "sound/audiostream.h"
#include "sound/mixer.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
#include "common/mutex.h"
namespace Audio {

View File

@ -31,7 +31,7 @@
#ifndef DISABLE_SID
#include "sid.h"
#include "sound/null.h"
#include "audio/null.h"
#include <math.h>
namespace Resid {
@ -1423,4 +1423,34 @@ int SID::clock(cycle_count& delta_t, short* buf, int n, int interleave) {
}
// Plugin interface
// (This can only create a null driver since C64 audio support is not part of the
// midi driver architecture. But we need the plugin for the options menu in the launcher
// and for MidiDriver::detectDevice() which is more or less used by all engines.)
class C64MusicPlugin : public NullMusicPlugin {
public:
const char *getName() const {
return _s("C64 Audio Emulator");
}
const char *getId() const {
return "C64";
}
MusicDevices getDevices() const;
};
MusicDevices C64MusicPlugin::getDevices() const {
MusicDevices devices;
devices.push_back(MusicDevice(this, "", MT_C64));
return devices;
}
//#if PLUGIN_ENABLED_DYNAMIC(C64)
//REGISTER_PLUGIN_DYNAMIC(C64, PLUGIN_TYPE_MUSIC, C64MusicPlugin);
//#else
REGISTER_PLUGIN_STATIC(C64, PLUGIN_TYPE_MUSIC, C64MusicPlugin);
//#endif
#endif

View File

@ -24,9 +24,9 @@
#include <math.h>
#include "sound/softsynth/ym2612.h"
#include "audio/softsynth/ym2612.h"
#include "common/util.h"
#include "sound/musicplugin.h"
#include "audio/musicplugin.h"
#include "common/translation.h"
////////////////////////////////////////
@ -677,14 +677,14 @@ 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*LOCAL_PI));
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));
powtbl[i] = (int)(0x10000 * pow(2.0, (i - 512) / 512.0));
}
{

View File

@ -27,7 +27,7 @@
#include "common/sys.h"
#include "sound/softsynth/emumidi.h"
#include "audio/softsynth/emumidi.h"
////////////////////////////////////////
//

View File

@ -23,7 +23,7 @@
*
*/
#include "sound/timestamp.h"
#include "audio/timestamp.h"
#include "common/algorithm.h"
namespace Audio {
@ -148,21 +148,9 @@ Timestamp Timestamp::addMsecs(int ms) const {
}
void Timestamp::addIntern(const Timestamp &ts) {
assert(_framerate == ts._framerate);
_secs += ts._secs;
if (_framerate == ts._framerate) {
_numFrames += ts._numFrames;
} else {
// We need to multiply by the quotient of the two framerates.
// We cancel the GCD in this fraction to reduce the risk of
// overflows.
const uint g = Common::gcd(_framerate, ts._framerate);
const uint p = _framerate / g;
const uint q = ts._framerate / g;
_framerate *= q;
_numFrames = _numFrames * q + ts._numFrames * p;
}
_numFrames += ts._numFrames;
normalize();
}
@ -187,24 +175,6 @@ Timestamp Timestamp::operator-(const Timestamp &ts) const {
return result;
}
/*
Timestamp &Timestamp::operator+=(const Timestamp &ts) {
addIntern(ts);
return *this;
}
Timestamp &Timestamp::operator-=(const Timestamp &ts) {
addIntern(-ts);
return *this;
}
*/
/*
int Timestamp::frameDiff(const Timestamp &ts) const {
return (*this - ts).totalNumberOfFrames();
}
*/
int Timestamp::frameDiff(const Timestamp &ts) const {
int delta = 0;

View File

@ -31,55 +31,62 @@
namespace Audio {
/**
* Timestamps allow measuring times with a sub-millisecond granularity,
* and without rounding losses. This is achieved by measuring frames
* instead of milliseconds: Specify an initial time in milliseconds
* plus framerate (in frames per second).
* Timestamps allow specifying points in time and measuring time intervals
* with a sub-millisecond granularity.
*
* When dealing with audio and video decoding, it is often necessary to
* measure time (intervals) in terms of frames, relative to a fixed
* frame rate (that is, a fixed number of frames per seconds). For
* example, in a typical video there are 24 frames per second, and in a
* typical sound there are 44100 frames (i.e. samples for mono sound
* and pairs of samples for stereo) per second.
*
* At the same time, the system clock provided by ScummVM measures time
* in milliseconds. For syncing purposes and other reasons, it is often
* necessary to convert between and compare time measures given on the
* one hand as a frame count, and on the other hand as a number of
* milliseconds.
*
* If handled carelessly, this can introduce rounding errors that
* quickly accumulate, resulting in user noticeable disturbance, such as
* audio and video running out of sync. E.g. a typical approach is to
* measure all time in milliseconds. But with a frame rate of 24 frames
* per second, one frame is 41.66666... milliseconds long. On the other
* hand, if measuring in frames, then similar rounding issue occur when
* converting from milliseconds to frames.
*
* One solution is to use floating point arithmetic to compute with
* fractional frames resp. (milli)seconds. This has other undesirable
* side effects; foremost, some platforms ScummVM runs on still have
* only limited (and slow) floating point support.
*
* This class provides an alternate solution: It stores time in terms of
* frames, but with a twist: Client code can specify arbitrary
* (integral) framerates; but internally, Timestamp modifies the
* framerate to be a multiple of 1000. This way, both numbers of frames
* (relative to the original framerate) as well as milliseconds can be
* represented as integers. This change is completely hidden from the
* user, however.
*
* A Timestamp can be converted to a frame count or milliseconds at
* virtually no cost. Likewise, it is posible to compute the difference
* between two Timestamps in milliseconds or number of frames.
* Timestamps can be easily compared using regular comparison operators,
* resulting in nicely readable code; this is even possible for
* timestamps that are specified using different framerates.
* Client code can modify Timestamps by adding a number of frames
* to it, or adding a number of milliseconds. Adding negative amounts is
* also allowed, and a Timestamp can even represent a "negative time"
* (mainly useful when using the Timestamp to store a time interval).
*/
class Timestamp {
protected:
/**
* The seconds part of this timestamp.
* The total time in seconds represented by this timestamp can be
* computed as follows:
* _secs + (double)_numFrames / _framerate
*/
int _secs;
/**
* The number of frames which together with _secs encodes
* the timestamp. The total number of frames represented
* by this timestamp is computed as follows:
* _numFrames + _secs * _framerate
*
* This is always a value greater or equal to zero.
* The only reason this is an int and not an uint is to
* allow intermediate negative values.
*/
int _numFrames;
/**
* The internal framerate, i.e. the number of frames per second.
* This is computed as the least common multiple of the framerate
* specified by the client code, and 1000.
* This way, we ensure that we can store both frames and
* milliseconds without any rounding losses.
*/
uint _framerate;
/**
* Factor by which the original framerate specified by the client
* code was multipled to obtain the internal _framerate value.
*/
uint _framerateFactor;
public:
/**
* Set up a timestamp with a given time and framerate.
* @param msecs starting time in milliseconds
* @param framerate number of frames per second (must be > 0)
*/
Timestamp(uint msecs, uint framerate);
Timestamp(uint msecs = 0, uint framerate = 1);
/**
* Set up a timestamp with a given time, frames and framerate.
@ -126,11 +133,17 @@ public:
// unary minus
Timestamp operator-() const;
/**
* Compute the sum of two timestamps. This is only
* allowed if they use the same framerate.
*/
Timestamp operator+(const Timestamp &ts) const;
Timestamp operator-(const Timestamp &ts) const;
// Timestamp &operator+=(const Timestamp &ts);
// Timestamp &operator-=(const Timestamp &ts);
/**
* Compute the difference between two timestamps. This is only
* allowed if they use the same framerate.
*/
Timestamp operator-(const Timestamp &ts) const;
/**
* Computes the number of frames between this timestamp and ts.
@ -176,7 +189,6 @@ public:
inline uint framerate() const { return _framerate / _framerateFactor; }
protected:
/**
* Compare this timestamp to another one and return
* a value similar to strcmp.
@ -193,6 +205,44 @@ protected:
* Add another timestamp to this one and normalize the result.
*/
void addIntern(const Timestamp &ts);
protected:
/**
* The seconds part of this timestamp.
* The total time in seconds represented by this timestamp can be
* computed as follows:
* _secs + (double)_numFrames / _framerate
*/
int _secs;
/**
* The number of frames which together with _secs encodes the
* timestamp. The total number of *internal* frames represented
* by this timestamp can be computed as follows:
* _numFrames + _secs * _framerate
* To obtain the number of frames with respect to the original
* framerate, this value has to be divided by _framerateFactor.
*
* This is always a value greater or equal to zero.
* The only reason this is an int and not an uint is to
* allow intermediate negative values.
*/
int _numFrames;
/**
* The internal framerate, i.e. the number of frames per second.
* This is computed as the least common multiple of the framerate
* specified by the client code, and 1000.
* This way, we ensure that we can store both frames and
* milliseconds without any rounding losses.
*/
uint _framerate;
/**
* Factor by which the original framerate specified by the client
* code was multipled to obtain the internal _framerate value.
*/
uint _framerateFactor;
};

148
backends/audiocd/audiocd.h Normal file
View File

@ -0,0 +1,148 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 BACKENDS_AUDIOCD_ABSTRACT_H
#define BACKENDS_AUDIOCD_ABSTRACT_H
#include "common/sys.h"
#include "common/noncopyable.h"
/**
* Abstract Audio CD manager class. Subclasses implement the actual
* functionality.
*/
class AudioCDManager : Common::NonCopyable {
public:
virtual ~AudioCDManager() {}
/**
* A structure containing the current playback information
*/
struct Status {
bool playing;
int track;
int start;
int duration;
int numLoops;
int volume;
int balance;
};
/**
* @name Emulated playback functions
* Engines should call these functions. Not all platforms
* support cd playback, and these functions should try to
* emulate it.
*/
//@{
/**
* Start audio CD playback
* @param track the track to play.
* @param num_loops how often playback should be repeated (-1 = infinitely often).
* @param start_frame the frame at which playback should start (75 frames = 1 second).
* @param duration the number of frames to play.
* @param only_emulate determines if the track should be emulated only
*/
virtual void play(int track, int numLoops, int startFrame, int duration, bool only_emulate = false) = 0;
/**
* Get if audio is being played.
* @return true if CD or emulated audio is playing
*/
virtual bool isPlaying() const = 0;
/**
* Set the audio volume
*/
virtual void setVolume(byte volume) = 0;
/**
* Set the speakers balance
*/
virtual void setBalance(int8 balance) = 0;
/**
* Stop CD or emulated audio playback.
*/
virtual void stop() = 0;
/**
* Update CD or emulated audio status.
*/
virtual void update() = 0;
/**
* Get the playback status.
* @return a Status struct with playback data.
*/
virtual Status getStatus() const = 0;
//@}
/**
* @name Real CD audio methods
* These functions should be called from the emulated
* ones if they can't emulate the audio playback.
*/
//@{
/**
* Initialise the specified CD drive for audio playback.
* @param drive the drive id
* @return true if the CD drive was inited succesfully
*/
virtual bool openCD(int drive) = 0;
/**
* Poll CD status.
* @return true if CD audio is playing
*/
virtual bool pollCD() const = 0;
/**
* Start CD audio playback.
* @param track the track to play.
* @param num_loops how often playback should be repeated (-1 = infinitely often).
* @param start_frame the frame at which playback should start (75 frames = 1 second).
* @param duration the number of frames to play.
*/
virtual void playCD(int track, int num_loops, int start_frame, int duration) = 0;
/**
* Stop CD audio playback.
*/
virtual void stopCD() = 0;
/**
* Update CD audio status.
*/
virtual void updateCD() = 0;
//@}
};
#endif

View File

@ -23,33 +23,24 @@
*
*/
#include "sound/audiocd.h"
#include "sound/audiostream.h"
#include "sound/decoders/mp3.h"
#include "sound/decoders/vorbis.h"
#include "sound/decoders/flac.h"
#include "engines/engine.h"
#include "common/util.h"
#include "backends/audiocd/default/default-audiocd.h"
#include "audio/audiostream.h"
#include "common/system.h"
DECLARE_SINGLETON(Audio::AudioCDManager)
namespace Audio {
AudioCDManager::AudioCDManager() {
DefaultAudioCDManager::DefaultAudioCDManager() {
_cd.playing = false;
_cd.track = 0;
_cd.start = 0;
_cd.duration = 0;
_cd.numLoops = 0;
_cd.volume = Mixer::kMaxChannelVolume;
_cd.volume = Audio::Mixer::kMaxChannelVolume;
_cd.balance = 0;
_mixer = g_system->getMixer();
_emulating = false;
assert(_mixer);
}
void AudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool only_emulate) {
void DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool only_emulate) {
if (numLoops != 0 || startFrame != 0) {
_cd.track = track;
_cd.numLoops = numLoops;
@ -65,14 +56,14 @@ void AudioCDManager::play(int track, int numLoops, int startFrame, int duration,
Audio::SeekableAudioStream *stream = 0;
for (int i = 0; !stream && i < 2; ++i)
stream = SeekableAudioStream::openStreamFile(trackName[i]);
stream = Audio::SeekableAudioStream::openStreamFile(trackName[i]);
// Stop any currently playing emulated track
_mixer->stopHandle(_handle);
if (stream != 0) {
Timestamp start = Timestamp(0, startFrame, 75);
Timestamp end = duration ? Timestamp(0, startFrame + duration, 75) : stream->getLength();
Audio::Timestamp start = Audio::Timestamp(0, startFrame, 75);
Audio::Timestamp end = duration ? Audio::Timestamp(0, startFrame + duration, 75) : stream->getLength();
/*
FIXME: Seems numLoops == 0 and numLoops == 1 both indicate a single repetition,
@ -80,39 +71,38 @@ void AudioCDManager::play(int track, int numLoops, int startFrame, int duration,
repetitions. Finally, -1 means infinitely many
*/
_emulating = true;
_mixer->playStream(Mixer::kMusicSoundType, &_handle,
makeLoopingAudioStream(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops), -1, _cd.volume, _cd.balance);
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle,
Audio::makeLoopingAudioStream(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops), -1, _cd.volume, _cd.balance);
} else {
_emulating = false;
if (!only_emulate)
g_system->playCD(track, numLoops, startFrame, duration);
playCD(track, numLoops, startFrame, duration);
}
}
}
void AudioCDManager::stop() {
void DefaultAudioCDManager::stop() {
if (_emulating) {
// Audio CD emulation
_mixer->stopHandle(_handle);
_emulating = false;
} else {
// Real Audio CD
g_system->stopCD();
stopCD();
}
}
bool AudioCDManager::isPlaying() const {
bool DefaultAudioCDManager::isPlaying() const {
if (_emulating) {
// Audio CD emulation
return _mixer->isSoundHandleActive(_handle);
} else {
// Real Audio CD
return g_system->pollCD();
return pollCD();
}
}
void AudioCDManager::setVolume(byte volume) {
void DefaultAudioCDManager::setVolume(byte volume) {
_cd.volume = volume;
if (_emulating) {
// Audio CD emulation
@ -120,7 +110,7 @@ void AudioCDManager::setVolume(byte volume) {
_mixer->setChannelVolume(_handle, _cd.volume);
} else {
// Real Audio CD
// Unfortunately I can't implement this atm
// since SDL doesn't seem to offer an interface method for this.
@ -128,7 +118,7 @@ void AudioCDManager::setVolume(byte volume) {
}
}
void AudioCDManager::setBalance(int8 balance) {
void DefaultAudioCDManager::setBalance(int8 balance) {
_cd.balance = balance;
if (_emulating) {
// Audio CD emulation
@ -136,7 +126,7 @@ void AudioCDManager::setBalance(int8 balance) {
_mixer->setChannelBalance(_handle, _cd.balance);
} else {
// Real Audio CD
// Unfortunately I can't implement this atm
// since SDL doesn't seem to offer an interface method for this.
@ -144,7 +134,7 @@ void AudioCDManager::setBalance(int8 balance) {
}
}
void AudioCDManager::updateCD() {
void DefaultAudioCDManager::update() {
if (_emulating) {
// Check whether the audio track stopped playback
if (!_mixer->isSoundHandleActive(_handle)) {
@ -156,16 +146,12 @@ void AudioCDManager::updateCD() {
_emulating = false;
}
} else {
g_system->updateCD();
updateCD();
}
}
AudioCDManager::Status AudioCDManager::getStatus() const {
// TODO: This could be improved for "real" CD playback.
// But to do that, we would have to extend the OSystem interface.
DefaultAudioCDManager::Status DefaultAudioCDManager::getStatus() const {
Status info = _cd;
info.playing = isPlaying();
return info;
}
} // End of namespace Audio

View File

@ -0,0 +1,62 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 BACKENDS_AUDIOCD_DEFAULT_H
#define BACKENDS_AUDIOCD_DEFAULT_H
#include "backends/audiocd/audiocd.h"
#include "audio/mixer.h"
/**
* The default audio cd manager. Implements emulation of audio cd playback.
*/
class DefaultAudioCDManager : public AudioCDManager {
public:
DefaultAudioCDManager();
virtual ~DefaultAudioCDManager() {}
void play(int track, int numLoops, int startFrame, int duration, bool only_emulate = false);
void stop();
bool isPlaying() const;
void setVolume(byte volume);
void setBalance(int8 balance);
void update();
virtual Status getStatus() const; // Subclasses should override for better status results
virtual bool openCD(int drive) { return false; }
virtual void updateCD() {}
virtual bool pollCD() const { return false; }
virtual void playCD(int track, int num_loops, int start_frame, int duration) {}
virtual void stopCD() {}
protected:
Audio::SoundHandle _handle;
bool _emulating;
Status _cd;
Audio::Mixer *_mixer;
};
#endif

View File

@ -0,0 +1,138 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 "common/sys.h"
#if defined(SDL_BACKEND)
#include "backends/audiocd/sdl/sdl-audiocd.h"
SdlAudioCDManager::SdlAudioCDManager()
:
_cdrom(0),
_cdTrack(0),
_cdNumLoops(0),
_cdStartFrame(0),
_cdDuration(0),
_cdEndTime(0),
_cdStopTime(0) {
}
SdlAudioCDManager::~SdlAudioCDManager() {
if (_cdrom) {
SDL_CDStop(_cdrom);
SDL_CDClose(_cdrom);
}
}
bool SdlAudioCDManager::openCD(int drive) {
if (SDL_InitSubSystem(SDL_INIT_CDROM) == -1)
_cdrom = NULL;
else {
_cdrom = SDL_CDOpen(drive);
// Did it open? Check if _cdrom is NULL
if (!_cdrom) {
warning("Couldn't open drive: %s", SDL_GetError());
} else {
_cdNumLoops = 0;
_cdStopTime = 0;
_cdEndTime = 0;
}
}
return (_cdrom != NULL);
}
void SdlAudioCDManager::stopCD() {
// Stop CD Audio in 1/10th of a second
_cdStopTime = SDL_GetTicks() + 100;
_cdNumLoops = 0;
}
void SdlAudioCDManager::playCD(int track, int num_loops, int start_frame, int duration) {
if (!num_loops && !start_frame)
return;
if (!_cdrom)
return;
if (duration > 0)
duration += 5;
_cdTrack = track;
_cdNumLoops = num_loops;
_cdStartFrame = start_frame;
SDL_CDStatus(_cdrom);
if (start_frame == 0 && duration == 0)
SDL_CDPlayTracks(_cdrom, track, 0, 1, 0);
else
SDL_CDPlayTracks(_cdrom, track, start_frame, 0, duration);
_cdDuration = duration;
_cdStopTime = 0;
_cdEndTime = SDL_GetTicks() + _cdrom->track[track].length * 1000 / CD_FPS;
}
bool SdlAudioCDManager::pollCD() const {
if (!_cdrom)
return false;
return (_cdNumLoops != 0 && (SDL_GetTicks() < _cdEndTime || SDL_CDStatus(_cdrom) == CD_PLAYING));
}
void SdlAudioCDManager::updateCD() {
if (!_cdrom)
return;
if (_cdStopTime != 0 && SDL_GetTicks() >= _cdStopTime) {
SDL_CDStop(_cdrom);
_cdNumLoops = 0;
_cdStopTime = 0;
return;
}
if (_cdNumLoops == 0 || SDL_GetTicks() < _cdEndTime)
return;
if (_cdNumLoops != 1 && SDL_CDStatus(_cdrom) != CD_STOPPED) {
// Wait another second for it to be done
_cdEndTime += 1000;
return;
}
if (_cdNumLoops > 0)
_cdNumLoops--;
if (_cdNumLoops != 0) {
if (_cdStartFrame == 0 && _cdDuration == 0)
SDL_CDPlayTracks(_cdrom, _cdTrack, 0, 1, 0);
else
SDL_CDPlayTracks(_cdrom, _cdTrack, _cdStartFrame, 0, _cdDuration);
_cdEndTime = SDL_GetTicks() + _cdrom->track[_cdTrack].length * 1000 / CD_FPS;
}
}
#endif

View File

@ -0,0 +1,53 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 BACKENDS_AUDIOCD_SDL_H
#define BACKENDS_AUDIOCD_SDL_H
#include "backends/audiocd/default/default-audiocd.h"
#include "backends/platform/sdl/sdl-sys.h"
/**
* The SDL audio cd manager. Implements real audio cd playback.
*/
class SdlAudioCDManager : public DefaultAudioCDManager {
public:
SdlAudioCDManager();
virtual ~SdlAudioCDManager();
protected:
virtual bool openCD(int drive);
virtual void updateCD();
virtual bool pollCD() const;
virtual void playCD(int track, int num_loops, int start_frame, int duration);
virtual void stopCD();
SDL_CD *_cdrom;
int _cdTrack, _cdNumLoops, _cdStartFrame, _cdDuration;
uint32 _cdEndTime, _cdStopTime;
};
#endif

View File

@ -1,80 +0,0 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 "backends/base-backend.h"
#include "backends/events/default/default-events.h"
#include "gui/message.h"
void BaseBackend::displayMessageOnOSD(const char *msg) {
// Display the message for 1.5 seconds
GUI::TimedMessageDialog dialog(msg, 1500);
dialog.runModal();
}
static Common::EventManager *s_eventManager = 0;
Common::EventManager *BaseBackend::getEventManager() {
// FIXME/TODO: Eventually this method should be turned into an abstract one,
// to force backends to implement this conciously (even if they
// end up returning the default event manager anyway).
if (!s_eventManager)
s_eventManager = new DefaultEventManager(this);
return s_eventManager;
}
/*
FIXME: Maybe we should push the default config file loading/saving code below
out to all the backends?
*/
#if defined(UNIX)
#if defined(SAMSUNGTV)
#define DEFAULT_CONFIG_FILE "/dtv/usb/sda1/.scummvmrc"
#else
#define DEFAULT_CONFIG_FILE ".residualrc"
#endif
#endif
#if !defined(UNIX)
#define DEFAULT_CONFIG_FILE "scummvm.ini"
#endif
Common::SeekableReadStream *BaseBackend::createConfigReadStream() {
Common::FSNode file(DEFAULT_CONFIG_FILE);
return file.createReadStream();
}
Common::WriteStream *BaseBackend::createConfigWriteStream() {
#ifdef __DC__
return 0;
#else
Common::FSNode file(DEFAULT_CONFIG_FILE);
return file.createWriteStream();
#endif
}

View File

@ -23,6 +23,8 @@
*
*/
#include "common/sys.h"
#if !defined(DISABLE_DEFAULT_EVENTMANAGER)
#include "common/system.h"

View File

@ -23,9 +23,14 @@
*
*/
#include "common/sys.h"
#if defined(SDL_BACKEND)
#include "backends/events/sdl/sdl-events.h"
#include "backends/platform/sdl/sdl.h"
#include "common/util.h"
#include "common/events.h"
#include "backends/graphics/graphics.h"
#include "common/config-manager.h"
// FIXME move joystick defines out and replace with confile file options
// we should really allow users to map any key to a joystick button
@ -46,10 +51,33 @@
#define JOY_BUT_SPACE 4
#define JOY_BUT_F5 5
SdlEventSource::SdlEventSource()
: _scrollLock(false), _joystick(0), _lastScreenID(0), EventSource() {
// Reset mouse state
memset(&_km, 0, sizeof(_km));
/* Residual doesn't support this
int joystick_num = ConfMan.getInt("joystick_num");
if (joystick_num > -1) {
// Initialize SDL joystick subsystem
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) {
error("Could not initialize SDL: %s", SDL_GetError());
}
// Enable joystick
if (SDL_NumJoysticks() > 0) {
printf("Using joystick: %s\n", SDL_JoystickName(0));
_joystick = SDL_JoystickOpen(joystick_num);
}
}*/
}
SdlEventSource::~SdlEventSource() {
/* Residual doesn't support this
if (_joystick)
SDL_JoystickClose(_joystick);*/
}
static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) {
int SdlEventSource::mapKey(SDLKey key, SDLMod mod, Uint16 unicode) {
if (key >= SDLK_F1 && key <= SDLK_F9) {
return key - SDLK_F1 + Common::ASCII_F1;
} else if (key >= SDLK_KP0 && key <= SDLK_KP9) {
@ -66,25 +94,17 @@ static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) {
return key;
}
void OSystem_SDL::fillMouseEvent(Common::Event &event, int x, int y) {
void SdlEventSource::fillMouseEvent(Common::Event &event, int x, int y) {
event.mouse.x = x;
event.mouse.y = y;
// Update the "keyboard mouse" coords
_km.x = x;
_km.y = y;
/* Residual doesn't support this
// Adjust for the screen scaling
if (!_overlayVisible) {
event.mouse.x /= _videoMode.scaleFactor;
event.mouse.y /= _videoMode.scaleFactor;
if (_videoMode.aspectRatioCorrection)
event.mouse.y = aspect2Real(event.mouse.y);
}*/
}
void OSystem_SDL::handleKbdMouse() {
uint32 curTime = getMillis();
void SdlEventSource::handleKbdMouse() {
uint32 curTime = g_system->getMillis();
if (curTime >= _km.last_time + _km.delay_time) {
_km.last_time = curTime;
if (_km.x_down_count == 1) {
@ -153,7 +173,7 @@ void OSystem_SDL::handleKbdMouse() {
}
}
static void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) {
void SdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) {
event.kbd.flags = 0;
@ -178,19 +198,19 @@ static void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) {
event.kbd.flags |= Common::KBD_CAPS;
}
bool OSystem_SDL::pollEvent(Common::Event &event) {
SDL_Event ev;
ev.type = SDL_NOEVENT;
bool SdlEventSource::pollEvent(Common::Event &event) {
handleKbdMouse();
/* Residual doesn't support this
// If the screen mode changed, send an Common::EVENT_SCREEN_CHANGED
if (_modeChanged) {
_modeChanged = false;
// If the screen changed, send an Common::EVENT_SCREEN_CHANGED
int screenID = ((OSystem_SDL *)g_system)->getGraphicsManager()->getScreenChangeID();
if (screenID != _lastScreenID) {
_lastScreenID = screenID;
event.type = Common::EVENT_SCREEN_CHANGED;
return true;
}
*/
}*/
SDL_Event ev;
ev.type = SDL_NOEVENT;
while (SDL_PollEvent(&ev)) {
preprocessEvents(&ev);
if (dispatchSDLEvent(ev, event))
@ -199,7 +219,7 @@ bool OSystem_SDL::pollEvent(Common::Event &event) {
return false;
}
bool OSystem_SDL::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
switch (ev.type) {
case SDL_KEYDOWN:
return handleKeyDown(ev, event);
@ -219,9 +239,16 @@ bool OSystem_SDL::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
return handleJoyAxisMotion(ev, event);
case SDL_VIDEOEXPOSE:
/* Residual doesn't support this */
//_forceFull = true;
break;
// HACK: Send a fake event, handled by SdlGraphicsManager
event.type = (Common::EventType)OSystem_SDL::kSdlEventExpose;
return true;
case SDL_VIDEORESIZE:
// HACK: Send a fake event, handled by OpenGLSdlGraphicsManager
event.type = (Common::EventType)OSystem_SDL::kSdlEventResize;
event.mouse.x = ev.resize.w;
event.mouse.y = ev.resize.h;
return true;
case SDL_QUIT:
event.type = Common::EVENT_QUIT;
@ -233,7 +260,7 @@ bool OSystem_SDL::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
}
bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) {
bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
SDLModToOSystemKeyFlags(SDL_GetModState(), event);
@ -244,42 +271,6 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) {
if (_scrollLock)
event.kbd.flags |= Common::KBD_SCRL;
// Alt-Return and Alt-Enter toggle full screen mode
/* Residual doesn't support this
if (event.kbd.hasFlags(Common::KBD_ALT) && (ev.key.keysym.sym == SDLK_RETURN || ev.key.keysym.sym == SDLK_KP_ENTER)) {
beginGFXTransaction();
setFullscreenMode(!_videoMode.fullscreen);
endGFXTransaction();
#ifdef USE_OSD
if (_videoMode.fullscreen)
displayMessageOnOSD("Fullscreen mode");
else
displayMessageOnOSD("Windowed mode");
#endif
return false;
}*/
/* // Alt-S: Create a screenshot
if (event.kbd.hasFlags(Common::KBD_ALT) && ev.key.keysym.sym == 's') {
char filename[20];
for (int n = 0;; n++) {
SDL_RWops *file;
sprintf(filename, "residual%05d.bmp", n);
file = SDL_RWFromFile(filename, "r");
if (!file)
break;
SDL_RWclose(file);
}
if (saveScreenshot(filename))
printf("Saved '%s'\n", filename);
else
printf("Could not save screenshot!\n");
return false;
}
*/
// Ctrl-m toggles mouse capture
if (event.kbd.hasFlags(Common::KBD_CTRL) && ev.key.keysym.sym == 'm') {
toggleMouseGrab();
@ -287,13 +278,13 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) {
}
#if defined(MACOSX)
// On Macintosh', Cmd-Q quits
// On Macintosh, Cmd-Q quits
if ((ev.key.keysym.mod & KMOD_META) && ev.key.keysym.sym == 'q') {
event.type = Common::EVENT_QUIT;
return true;
}
#elif defined(UNIX)
// On other unices, Control-Q quits
// On other *nix systems, Control-Q quits
if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'q') {
event.type = Common::EVENT_QUIT;
return true;
@ -306,16 +297,11 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) {
}
#endif
// Ctrl-u toggles mute
if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'u') {
event.type = Common::EVENT_MUTE;
return true;
}
/* Residual doesn't support this
// Ctrl-Alt-<key> will change the GFX mode
if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
if (handleScalerHotkeys(ev.key))
return false;
}*/
if (remapKey(ev, event))
return true;
@ -327,38 +313,65 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) {
return true;
}
bool OSystem_SDL::handleKeyUp(SDL_Event &ev, Common::Event &event) {
bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) {
if (remapKey(ev, event))
return true;
SDLMod mod = SDL_GetModState();
// Check if this is an event handled by handleKeyDown(), and stop if it is
// Check if the Ctrl key is down, so that we can trap cases where the
// user has the Ctrl key down, and has just released a special key
if (mod & KMOD_CTRL) {
if (ev.key.keysym.sym == 'm' || // Ctrl-m toggles mouse capture
#if defined(MACOSX)
// Meta - Q, handled below
#elif defined(UNIX)
ev.key.keysym.sym == 'q' || // On other *nix systems, Control-Q quits
#else
ev.key.keysym.sym == 'z' || // Ctrl-z quit
#endif
ev.key.keysym.sym == 'u') // Ctrl-u toggles mute
return false;
}
// Same for other keys (Meta and Alt)
#if defined(MACOSX)
if ((mod & KMOD_META) && ev.key.keysym.sym == 'q')
return false; // On Macintosh, Cmd-Q quits
#elif defined(UNIX)
// Control Q has already been handled above
#else
if ((mod & KMOD_ALT) && ev.key.keysym.sym == 'x')
return false; // Alt-x quit
#endif
// If we reached here, this isn't an event handled by handleKeyDown(), thus
// continue normally
event.type = Common::EVENT_KEYUP;
event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);
// Ctrl-Alt-<key> will change the GFX mode
SDLModToOSystemKeyFlags(SDL_GetModState(), event);
SDLModToOSystemKeyFlags(mod, event);
// Set the scroll lock sticky flag
if (_scrollLock)
event.kbd.flags |= Common::KBD_SCRL;
/* Residual doesn't support this
if (isScalerHotkey(event))
// Swallow these key up events
return false;*/
return true;
}
bool OSystem_SDL::handleMouseMotion(SDL_Event &ev, Common::Event &event) {
bool SdlEventSource::handleMouseMotion(SDL_Event &ev, Common::Event &event) {
event.type = Common::EVENT_MOUSEMOVE;
fillMouseEvent(event, ev.motion.x, ev.motion.y);
/* Residual doesn't support this */
//setMousePos(event.mouse.x, event.mouse.y);
return true;
}
bool OSystem_SDL::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
bool SdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
if (ev.button.button == SDL_BUTTON_LEFT)
event.type = Common::EVENT_LBUTTONDOWN;
else if (ev.button.button == SDL_BUTTON_RIGHT)
@ -381,7 +394,7 @@ bool OSystem_SDL::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
return true;
}
bool OSystem_SDL::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
bool SdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
if (ev.button.button == SDL_BUTTON_LEFT)
event.type = Common::EVENT_LBUTTONUP;
else if (ev.button.button == SDL_BUTTON_RIGHT)
@ -397,7 +410,7 @@ bool OSystem_SDL::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
return true;
}
bool OSystem_SDL::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
if (ev.jbutton.button == JOY_BUT_LMOUSE) {
event.type = Common::EVENT_LBUTTONDOWN;
fillMouseEvent(event, _km.x, _km.y);
@ -428,7 +441,7 @@ bool OSystem_SDL::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
return true;
}
bool OSystem_SDL::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
if (ev.jbutton.button == JOY_BUT_LMOUSE) {
event.type = Common::EVENT_LBUTTONUP;
fillMouseEvent(event, _km.x, _km.y);
@ -459,7 +472,7 @@ bool OSystem_SDL::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
return true;
}
bool OSystem_SDL::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) {
bool SdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) {
int axis = ev.jaxis.value;
if ( axis > JOY_DEADZONE) {
axis -= JOY_DEADZONE;
@ -472,7 +485,7 @@ bool OSystem_SDL::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) {
if ( ev.jaxis.axis == JOY_XAXIS) {
#ifdef JOY_ANALOG
_km.x_vel = axis/2000;
_km.x_vel = axis / 2000;
_km.x_down_count = 0;
#else
if (axis != 0) {
@ -507,7 +520,7 @@ bool OSystem_SDL::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) {
return true;
}
bool OSystem_SDL::remapKey(SDL_Event &ev, Common::Event &event) {
bool SdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
#ifdef LINUPY
// On Yopy map the End button to quit
if ((ev.key.keysym.sym == 293)) {
@ -574,3 +587,19 @@ bool OSystem_SDL::remapKey(SDL_Event &ev, Common::Event &event) {
#endif
return false;
}
void SdlEventSource::toggleMouseGrab() {
if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF)
SDL_WM_GrabInput(SDL_GRAB_ON);
else
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
void SdlEventSource::resetKeyboadEmulation(int16 x_max, int16 y_max) {
_km.x_max = x_max;
_km.y_max = y_max;
_km.delay_time = 25;
_km.last_time = 0;
}
#endif

View File

@ -0,0 +1,135 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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$
*
*/
#if !defined(BACKEND_EVENTS_SDL_H) && !defined(DISABLE_DEFAULT_EVENTMANAGER)
#define BACKEND_EVENTS_SDL_H
#include "backends/events/default/default-events.h"
#include "backends/platform/sdl/sdl-sys.h"
/**
* The SDL event source.
*/
class SdlEventSource : public Common::EventSource {
public:
SdlEventSource();
virtual ~SdlEventSource();
/**
* Gets and processes SDL events.
*/
virtual bool pollEvent(Common::Event &event);
/**
* Resets keyboard emulation after a video screen change
*/
virtual void resetKeyboadEmulation(int16 x_max, int16 y_max);
/**
* Toggles mouse input grab
*/
virtual void toggleMouseGrab();
protected:
/** @name Keyboard mouse emulation
* Disabled by fingolfin 2004-12-18.
* I am keeping the rest of the code in for now, since the joystick
* code (or rather, "hack") uses it, too.
*/
//@{
struct KbdMouse {
int16 x, y, x_vel, y_vel, x_max, y_max, x_down_count, y_down_count;
uint32 last_time, delay_time, x_down_time, y_down_time;
};
KbdMouse _km;
//@}
/** Scroll lock state - since SDL doesn't track it */
bool _scrollLock;
/** Joystick */
SDL_Joystick *_joystick;
/** Last screen id for checking if it was modified */
int _lastScreenID;
/**
* Pre process an event before it is dispatched.
*/
virtual void preprocessEvents(SDL_Event *event) {}
/**
* Dispatchs SDL events for each handler.
*/
virtual bool dispatchSDLEvent(SDL_Event &ev, Common::Event &event);
/** @name Event Handlers
* Handlers for specific SDL events, called by SdlEventSource::dispatchSDLEvent().
* This way, if a managers inherits fromt this SDL events manager, it can
* change the behavior of only a single event, without having to override all
* of SdlEventSource::dispatchSDLEvent().
*/
//@{
virtual bool handleKeyDown(SDL_Event &ev, Common::Event &event);
virtual bool handleKeyUp(SDL_Event &ev, Common::Event &event);
virtual bool handleMouseMotion(SDL_Event &ev, Common::Event &event);
virtual bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event);
virtual bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
virtual bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event);
virtual bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event);
virtual bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event);
virtual void handleKbdMouse();
//@}
/**
* Assigns the mouse coords to the mouse event
*/
virtual void fillMouseEvent(Common::Event &event, int x, int y);
/**
* Remaps key events. This allows platforms to configure
* their custom keys.
*/
virtual bool remapKey(SDL_Event &ev, Common::Event &event);
/**
* Maps the ASCII value of key
*/
virtual int mapKey(SDLKey key, SDLMod mod, Uint16 unicode);
/**
* Configures the key modifiers flags status
*/
virtual void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event);
};
#endif

View File

@ -23,6 +23,9 @@
*
*/
// Disable symbol overrides so that we can use FILE, fopen etc.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/fs/stdiostream.h"
StdioStream::StdioStream(void *handle) : _handle(handle) {

View File

@ -22,7 +22,11 @@
* $Id$
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#if defined(WIN32)
#include "backends/fs/windows/windows-fs-factory.h"
#include "backends/fs/windows/windows-fs.cpp"

View File

@ -0,0 +1,67 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 BACKENDS_GRAPHICS_ABSTRACT_H
#define BACKENDS_GRAPHICS_ABSTRACT_H
#include "common/system.h"
#include "common/noncopyable.h"
#include "common/keyboard.h"
/**
* Abstract class for graphics manager. Subclasses
* implement the real functionality.
*/
class GraphicsManager : Common::NonCopyable {
public:
virtual ~GraphicsManager() {}
virtual bool hasFeature(OSystem::Feature f) = 0;
virtual void setFeatureState(OSystem::Feature f, bool enable) = 0;
virtual bool getFeatureState(OSystem::Feature f) = 0;
virtual void launcherInitSize(uint w, uint h) = 0;
virtual byte *setupScreen(int screenW, int screenH, bool fullscreen, bool accel3d) = 0;
virtual int16 getHeight() = 0;
virtual int16 getWidth() = 0;
virtual void updateScreen() = 0;
virtual void showOverlay() = 0;
virtual void hideOverlay() = 0;
virtual Graphics::PixelFormat getOverlayFormat() const = 0;
virtual void clearOverlay() = 0;
virtual void grabOverlay(OverlayColor *buf, int pitch) = 0;
virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h)= 0;
virtual int16 getOverlayHeight() = 0;
virtual int16 getOverlayWidth() = 0;
virtual bool showMouse(bool visible) = 0;
virtual void warpMouse(int x, int y) = 0;
virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale = 1, const Graphics::PixelFormat *format = NULL) = 0;
virtual void displayMessageOnOSD(const char *msg) {}
};
#endif

View File

@ -23,7 +23,14 @@
*
*/
#include "common/sys.h"
#if defined(SDL_BACKEND)
#include "backends/graphics/sdl/sdl-graphics.h"
#include "backends/events/sdl/sdl-events.h"
#include "backends/platform/sdl/sdl.h"
#include "common/config-manager.h"
#include "common/mutex.h"
#include "common/translation.h"
#include "common/util.h"
@ -32,17 +39,70 @@
#endif
#include "graphics/font.h"
#include "graphics/fontman.h"
#include "graphics/scaler.h"
#include "graphics/surface.h"
SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *sdlEventSource)
:
_sdlEventSource(sdlEventSource),
_screen(0),
_overlayVisible(false),
_overlayscreen(0),
_overlayWidth(0), _overlayHeight(0),
_overlayDirty(true), _overlayNumTex(0)
#ifdef USE_OPENGL
, _overlayTexIds(0) {
#else
{
#endif
if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) {
error("Could not initialize SDL: %s", SDL_GetError());
}
// This is also called in initSDL(), but initializing graphics
// may reset it.
SDL_EnableUNICODE(1);
void OSystem_SDL::launcherInitSize(uint w, uint h) {
#ifdef _WIN32_WCE
if (ConfMan.hasKey("use_GDI") && ConfMan.getBool("use_GDI")) {
SDL_VideoInit("windib", 0);
sdlFlags ^= SDL_INIT_VIDEO;
}
#endif
}
SdlGraphicsManager::~SdlGraphicsManager() {
// Unregister the event observer
if (g_system->getEventManager()->getEventDispatcher() != NULL)
g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
}
void SdlGraphicsManager::initEventObserver() {
// Register the graphics manager as a event observer
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false);
}
bool SdlGraphicsManager::hasFeature(OSystem::Feature f) {
return
#ifdef USE_OPENGL
(f == OSystem::kFeatureOpenGL);
#else
false;
#endif
}
void SdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
}
bool SdlGraphicsManager::getFeatureState(OSystem::Feature f) {
return false;
}
void SdlGraphicsManager::launcherInitSize(uint w, uint h) {
closeOverlay();
setupScreen(w, h, false, false);
}
byte *OSystem_SDL::setupScreen(int screenW, int screenH, bool fullscreen, bool accel3d) {
byte *SdlGraphicsManager::setupScreen(int screenW, int screenH, bool fullscreen, bool accel3d) {
uint32 sdlflags;
int bpp;
@ -161,7 +221,7 @@ byte *OSystem_SDL::setupScreen(int screenW, int screenH, bool fullscreen, bool a
#define BITMAP_TEXTURE_SIZE 256
void OSystem_SDL::updateScreen() {
void SdlGraphicsManager::updateScreen() {
#ifdef USE_OPENGL
if (_opengl) {
if (_overlayVisible) {
@ -265,11 +325,11 @@ void OSystem_SDL::updateScreen() {
}
}
int16 OSystem_SDL::getHeight() {
int16 SdlGraphicsManager::getHeight() {
return _screen->h;
}
int16 OSystem_SDL::getWidth() {
int16 SdlGraphicsManager::getWidth() {
return _screen->w;
}
@ -278,7 +338,7 @@ int16 OSystem_SDL::getWidth() {
#pragma mark --- Overlays ---
#pragma mark -
void OSystem_SDL::showOverlay() {
void SdlGraphicsManager::showOverlay() {
if (_overlayVisible)
return;
@ -287,7 +347,8 @@ void OSystem_SDL::showOverlay() {
clearOverlay();
}
void OSystem_SDL::hideOverlay() {
void SdlGraphicsManager::hideOverlay() {
if (!_overlayVisible)
return;
@ -296,7 +357,8 @@ void OSystem_SDL::hideOverlay() {
clearOverlay();
}
void OSystem_SDL::clearOverlay() {
void SdlGraphicsManager::clearOverlay() {
if (!_overlayVisible)
return;
@ -324,7 +386,7 @@ void OSystem_SDL::clearOverlay() {
_overlayDirty = true;
}
void OSystem_SDL::grabOverlay(OverlayColor *buf, int pitch) {
void SdlGraphicsManager::grabOverlay(OverlayColor *buf, int pitch) {
if (_overlayscreen == NULL)
return;
@ -342,7 +404,7 @@ void OSystem_SDL::grabOverlay(OverlayColor *buf, int pitch) {
SDL_UnlockSurface(_overlayscreen);
}
void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
void SdlGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
if (_overlayscreen == NULL)
return;
@ -383,16 +445,7 @@ void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, i
SDL_UnlockSurface(_overlayscreen);
}
#pragma mark -
#pragma mark --- Mouse ---
#pragma mark -
bool OSystem_SDL::showMouse(bool visible) {
return false;
}
void OSystem_SDL::closeOverlay() {
void SdlGraphicsManager::closeOverlay() {
if (_overlayscreen) {
SDL_FreeSurface(_overlayscreen);
_overlayscreen = NULL;
@ -406,111 +459,20 @@ void OSystem_SDL::closeOverlay() {
}
}
void OSystem_SDL::warpMouse(int x, int y) {
#pragma mark -
#pragma mark --- Mouse ---
#pragma mark -
bool SdlGraphicsManager::showMouse(bool visible) {
return false;
}
void SdlGraphicsManager::warpMouse(int x, int y) {
SDL_WarpMouse(x, y);
/* Residual doesn't support this
int y1 = y;
// Don't change mouse position, when mouse is outside of our window (in case of windowed mode)
if (!(SDL_GetAppState( ) & SDL_APPMOUSEFOCUS))
return;
if (_videoMode.aspectRatioCorrection && !_overlayVisible)
y1 = real2Aspect(y);
if (_mouseCurState.x != x || _mouseCurState.y != y) {
if (!_overlayVisible)
SDL_WarpMouse(x * _videoMode.scaleFactor, y1 * _videoMode.scaleFactor);
else
SDL_WarpMouse(x, y1);
// SDL_WarpMouse() generates a mouse movement event, so
// setMousePos() would be called eventually. However, the
// cannon script in CoMI calls this function twice each time
// the cannon is reloaded. Unless we update the mouse position
// immediately the second call is ignored, causing the cannon
// to change its aim.
setMousePos(x, y);
}*/
}
void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
#ifdef USE_RGB_COLOR
if (!format)
_cursorFormat = Graphics::PixelFormat::createFormatCLUT8();
else if (format->bytesPerPixel <= _screenFormat.bytesPerPixel)
_cursorFormat = *format;
bool SdlGraphicsManager::notifyEvent(const Common::Event &event) {
return false;
}
if (_cursorFormat.bytesPerPixel < 4)
assert(keycolor < (uint)(1 << (_cursorFormat.bytesPerPixel << 3)));
#else
assert(keycolor <= 0xFF);
#endif
if (w == 0 || h == 0)
return;
/* Residual doesn't support this
_mouseCurState.hotX = hotspot_x;
_mouseCurState.hotY = hotspot_y;
_mouseKeyColor = keycolor;
_cursorTargetScale = cursorTargetScale;
_mouseTextureId = new GLuint[1];
glGenTextures(1, _mouseTextureId);
glBindTexture(GL_TEXTURE_2D, _overlayTexIds[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, BITMAP_TEXTURE_SIZE, BITMAP_TEXTURE_SIZE, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
glPixelStorei(GL_UNPACK_ROW_LENGTH, _overlayWidth);
glBindTexture(GL_TEXTURE_2D, _overlayTexIds[curTexIdx]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _mouseWidth, _mouseHeight, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (byte *)buf + (y * 2 * _mouseWidth) + (2 * x));
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) {
_mouseCurState.w = w;
_mouseCurState.h = h;
if (_mouseOrigSurface)
SDL_FreeSurface(_mouseOrigSurface);
_mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
_mouseCurState.w,
_mouseCurState.h,
16,
_hwscreen->format->Rmask,
_hwscreen->format->Gmask,
_hwscreen->format->Bmask,
_hwscreen->format->Amask);
if (_mouseOrigSurface == NULL)
error("allocating _mouseOrigSurface failed");
SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
}
free(_mouseData);
#ifdef USE_RGB_COLOR
_mouseData = (byte *)malloc(w * h * _cursorFormat.bytesPerPixel);
memcpy(_mouseData, buf, w * h * _cursorFormat.bytesPerPixel);
#else
_mouseData = (byte *)malloc(w * h);
memcpy(_mouseData, buf, w * h);
#endif
blitCursor();*/
}
void OSystem_SDL::toggleMouseGrab() {
if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF)
SDL_WM_GrabInput(SDL_GRAB_ON);
else
SDL_WM_GrabInput(SDL_GRAB_OFF);
}

View File

@ -0,0 +1,111 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 BACKENDS_GRAPHICS_SDL_H
#define BACKENDS_GRAPHICS_SDL_H
#ifdef USE_OPENGL
#include <SDL_opengl.h>
#endif
#include "backends/graphics/graphics.h"
#include "graphics/scaler.h"
#include "common/events.h"
#include "common/system.h"
#include "backends/events/sdl/sdl-events.h"
#include "backends/platform/sdl/sdl-sys.h"
/**
* SDL graphics manager
*/
class SdlGraphicsManager : public GraphicsManager, public Common::EventObserver {
public:
SdlGraphicsManager(SdlEventSource *sdlEventSource);
virtual ~SdlGraphicsManager();
virtual void initEventObserver();
virtual bool hasFeature(OSystem::Feature f);
virtual void setFeatureState(OSystem::Feature f, bool enable);
virtual bool getFeatureState(OSystem::Feature f);
virtual void launcherInitSize(uint w, uint h);
byte *setupScreen(int screenW, int screenH, bool fullscreen, bool accel3d);
virtual int16 getHeight();
virtual int16 getWidth();
public:
virtual void updateScreen();
virtual void showOverlay();
virtual void hideOverlay();
virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; }
virtual void clearOverlay();
virtual void grabOverlay(OverlayColor *buf, int pitch);
virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
virtual int16 getOverlayHeight() { return _overlayHeight; }
virtual int16 getOverlayWidth() { return _overlayWidth; }
void closeOverlay();
virtual bool showMouse(bool visible);
virtual void warpMouse(int x, int y);
void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale = 1, const Graphics::PixelFormat *format = NULL) {}
#ifdef USE_OSD
virtual void displayMessageOnOSD(const char *msg);
#endif
// Override from Common::EventObserver
bool notifyEvent(const Common::Event &event);
protected:
SdlEventSource *_sdlEventSource;
SDL_Surface *_screen;
#ifdef USE_OPENGL
bool _opengl;
#endif
bool _fullscreen;
// overlay
SDL_Surface *_overlayscreen;
bool _overlayVisible;
Graphics::PixelFormat _overlayFormat;
int _overlayWidth, _overlayHeight;
bool _overlayDirty;
#ifdef USE_OPENGL
int _overlayNumTex;
GLuint *_overlayTexIds;
#endif
/** Force full redraw on next updateScreen */
bool _forceFull;
};
#endif

View File

@ -26,9 +26,9 @@
#ifdef ENABLE_KEYMAPPER
#include "gui/GuiManager.h"
#include "gui/PopUpWidget.h"
#include "gui/ScrollBarWidget.h"
#include "gui/gui-manager.h"
#include "gui/widgets/popup.h"
#include "gui/widgets/scrollbar.h"
#include "gui/ThemeEval.h"
#include "common/translation.h"

108
backends/log/log.cpp Normal file
View File

@ -0,0 +1,108 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 "backends/log/log.h"
#include "common/stream.h"
#include "common/str.h"
#include "common/system.h"
#include "base/version.h"
namespace Backends {
namespace Log {
Log::Log(OSystem *system)
: _system(system), _stream(0), _startOfLine(true) {
assert(system);
}
void Log::open(Common::WriteStream *stream) {
// Close the previous log
close();
_stream = stream;
// Output information about the ScummVM version at the start of the log
// file
print(gResidualFullVersion);
print("\n");
print(gResidualFeatures);
print("\n");
print("--- Log opened.\n");
_startOfLine = true;
}
void Log::close() {
if (_stream) {
// Output a message to indicate that the log was closed successfully
print("--- Log closed successfully.\n");
delete _stream;
_stream = 0;
}
}
void Log::print(const char *message, const bool printTime) {
if (!_stream)
return;
while (*message) {
if (_startOfLine) {
_startOfLine = false;
if (printTime)
printTimeStamp();
}
const char *msgStart = message;
// scan for end of line/string
while (*message && *message != '\n')
++message;
if (*message == '\n') {
++message;
_startOfLine = true;
}
// TODO: It might be wise to check for write errors and/or incomplete
// writes here, since losing certain bits of the log is not nice.
_stream->write(msgStart, message - msgStart);
}
_stream->flush();
}
void Log::printTimeStamp() {
TimeDate date;
_system->getTimeAndDate(date);
_stream->writeString(Common::String::format("[%d-%02d-%02d %02d:%02d:%02d] ",
date.tm_year + 1900, date.tm_mon, date.tm_mday,
date.tm_hour, date.tm_min, date.tm_sec));
}
} // End of namespace Log
} // End of namespace Backends

132
backends/log/log.h Normal file
View File

@ -0,0 +1,132 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 BACKENDS_LOG_LOG_H
#define BACKENDS_LOG_LOG_H
#include "common/sys.h"
class OSystem;
namespace Common {
class WriteStream;
} // End of namespace Common
namespace Backends {
namespace Log {
/**
* Log file writer.
*
* This can be used by the backends to implement file logging functionality.
*/
class Log {
public:
/**
* Constructor for the logger object.
*
* @param system The OSystem instance to use. Must be non-null.
*/
Log(OSystem *system);
~Log() { close(); }
/**
* Opens a new log file.
*
* The previous log, which was handled by this logger, will be closed
* before the new stream is associated.
*
* The current implemention will always call flush after data is written
* to the log file. It might thus be wise to pass an unbuffered write
* stream here to avoid unnecessary overhead.
* @see Common::WriteStream::flush
*
* Calling open with stream being 0 is valid and will result in the same
* behavior as calling close, but it may have additional overhead.
* @see close
*
* This function will output information about the ScummVM version and
* the features built into ScummVM automatically. It will also add a short
* notice to indicate that the log was opened successfully.
*
* @param stream Stream where to output the log contents.
* Note that the stream will be deleted by the logger.
*/
void open(Common::WriteStream *stream);
/**
* Closes the current log file.
*
* This function will output a line saying that the log was closed
* successfully. This can be used to check whether a log is incomplete
* because of whatever reasons.
*/
void close();
/**
* Prints a message to the log stream.
*
* This has optional support to output a timestamp on every new line.
* The timestamp will look like: "[YYYY-MM-DD HH:MM:SS] ".
* Printing of a timestamp is done by default.
*
* It might be noteworthy that this function does not append a new line
* to the given message.
*
* In case no stream is associated with this logger, this function will
* quit immediatly.
*
* @param message The message to write.
* @param printTimeOnNewline Whether to print a timestamp on the start of
* a new line.
*/
void print(const char *message, const bool printTimeOnNewline = true);
private:
/**
* Prints a time stamp in the form: "[YYYY-MM-DD HH:MM:SS] ".
*/
void printTimeStamp();
/**
* The OSystem instance used to query data like the time.
*/
OSystem *_system;
/**
* Where to write the output too.
*/
Common::WriteStream *_stream;
/**
* Whether we are at the start of a line.
*/
bool _startOfLine;
};
} // End of namespace Log
} // End of namespace Backends
#endif

View File

@ -22,14 +22,17 @@
* $Id$
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/sys.h"
#if defined(USE_ALSA)
#include "common/config-manager.h"
#include "common/util.h"
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include <alsa/asoundlib.h>
@ -41,7 +44,7 @@
#if SND_LIB_MAJOR >= 1 || SND_LIB_MINOR >= 6
#define snd_seq_flush_output(x) snd_seq_drain_output(x)
#define snd_seq_set_client_group(x,name) /*nop */
#define snd_seq_set_client_group(x,name) /*nop */
#define my_snd_seq_open(seqp) snd_seq_open(seqp, "hw", SND_SEQ_OPEN_DUPLEX, 0)
#else
/* SND_SEQ_OPEN_OUT causes oops on early version of ALSA */
@ -50,9 +53,8 @@
#define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
static int check_permission(snd_seq_port_info_t *pinfo)
{
if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) {
static int check_permission(snd_seq_port_info_t *pinfo) {
if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) {
if (!(snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT))
return 1;
}
@ -65,10 +67,11 @@ static int check_permission(snd_seq_port_info_t *pinfo)
#define ADDR_DELIM ".:"
class MidiDriver_ALSA:public MidiDriver_MPU401 {
class MidiDriver_ALSA : public MidiDriver_MPU401 {
public:
MidiDriver_ALSA(int client, int port);
int open();
bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@ -80,11 +83,12 @@ private:
snd_seq_t *seq_handle;
int seq_client, seq_port;
int my_client, my_port;
// The volume controller value of the first MIDI channel
int8 _channel0Volume;
};
MidiDriver_ALSA::MidiDriver_ALSA(int client, int port)
: _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0)
{
: _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0), _channel0Volume(127) {
memset(&ev, 0, sizeof(ev));
}
@ -111,7 +115,7 @@ int MidiDriver_ALSA::open() {
// with those capabilities.
my_port = snd_seq_create_simple_port(seq_handle, "RESIDUAL port 0", 0,
SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
if (my_port < 0) {
snd_seq_close(seq_handle);
@ -205,24 +209,41 @@ void MidiDriver_ALSA::send(uint32 b) {
case 0xB0:
/* is it this simple ? Wow... */
snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]);
// We save the volume of the first MIDI channel here to utilize it in
// our workaround for broken USB-MIDI cables.
if (chanID == 0 && midiCmd[1] == 0x07)
_channel0Volume = midiCmd[2];
send_event(1);
break;
case 0xC0:
snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]);
send_event(0);
// Send a volume change command to work around a firmware bug in common
// USB-MIDI cables. If the first MIDI command in a USB packet is a
// Cx or Dx command, the second command in the packet is dropped
// somewhere.
send(0x07B0 | (_channel0Volume << 16));
break;
case 0xD0:
snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]);
send_event(1);
// Send a volume change command to work around a firmware bug in common
// USB-MIDI cables. If the first MIDI command in a USB packet is a
// Cx or Dx command, the second command in the packet is dropped
// somewhere.
send(0x07B0 | (_channel0Volume << 16));
break;
case 0xE0:{
// long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4;
// snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000;
snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
send_event(1);
}
break;
case 0xE0: {
// long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4;
// snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000;
snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
send_event(1);
} break;
default:
warning("Unknown MIDI Command: %08x", (int)b);
@ -277,6 +298,9 @@ typedef Common::List<AlsaDevice> AlsaDevices;
AlsaDevice::AlsaDevice(Common::String name, MusicType mt, int client)
: _name(name), _type(mt), _client(client) {
// Make sure we do not get any trailing spaces to avoid problems when
// storing the name in the configuration file.
_name.trim();
}
Common::String AlsaDevice::getName() {

View File

@ -22,14 +22,17 @@
* $Id$
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/sys.h"
#if defined(__amigaos4__)
#include "common/endian.h"
#include "common/util.h"
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include <proto/camd.h>
#include <proto/exec.h>
@ -43,6 +46,7 @@ class MidiDriver_CAMD : public MidiDriver_MPU401 {
public:
MidiDriver_CAMD();
int open();
bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@ -79,7 +83,7 @@ int MidiDriver_CAMD::open() {
}
struct MidiNode *midi_node;
midi_node = _ICamd->CreateMidi(MIDI_MsgQueue, 0L, MIDI_SysExSize, 4096L, MIDI_Name, "scummvm", TAG_END);
midi_node = _ICamd->CreateMidi(MIDI_MsgQueue, 0L, MIDI_SysExSize, 4096L, MIDI_Name, "residual", TAG_END);
if (!midi_node) {
closeAll();
error("Could not create CAMD MIDI node");

View File

@ -22,6 +22,11 @@
* $Id$
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/sys.h"
#ifdef MACOSX
// HACK to disable deprecated warnings under Mac OS X 10.5.
@ -37,8 +42,8 @@
#include "common/config-manager.h"
#include "common/util.h"
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include <CoreServices/CoreServices.h>
#include <AudioToolbox/AUGraph.h>
@ -67,7 +72,9 @@ do { \
class MidiDriver_CORE : public MidiDriver_MPU401 {
public:
MidiDriver_CORE();
~MidiDriver_CORE();
int open();
bool isOpen() const { return _auGraph != 0; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@ -81,10 +88,18 @@ MidiDriver_CORE::MidiDriver_CORE()
: _auGraph(0) {
}
MidiDriver_CORE::~MidiDriver_CORE() {
if (_auGraph) {
AUGraphStop(_auGraph);
DisposeAUGraph(_auGraph);
_auGraph = 0;
}
}
int MidiDriver_CORE::open() {
OSStatus err = 0;
if (_auGraph)
if (isOpen())
return MERR_ALREADY_OPEN;
// Open the Music Device.
@ -171,7 +186,6 @@ bail:
void MidiDriver_CORE::close() {
MidiDriver_MPU401::close();
if (_auGraph) {
AUGraphStop(_auGraph);
DisposeAUGraph(_auGraph);
@ -180,7 +194,7 @@ void MidiDriver_CORE::close() {
}
void MidiDriver_CORE::send(uint32 b) {
assert(_auGraph != NULL);
assert(isOpen());
byte status_byte = (b & 0x000000FF);
byte first_byte = (b & 0x0000FF00) >> 8;
@ -193,7 +207,7 @@ void MidiDriver_CORE::sysEx(const byte *msg, uint16 length) {
unsigned char buf[266];
assert(length + 2 <= ARRAYSIZE(buf));
assert(_auGraph != NULL);
assert(isOpen());
// Add SysEx frame
buf[0] = 0xF0;

View File

@ -22,12 +22,17 @@
* $Id$
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/sys.h"
#ifdef MACOSX
#include "common/config-manager.h"
#include "common/util.h"
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include <CoreMIDI/CoreMIDI.h>
@ -51,6 +56,7 @@ public:
MidiDriver_CoreMIDI();
~MidiDriver_CoreMIDI();
int open();
bool isOpen() const { return mOutPort != 0 && mDest != 0; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@ -65,7 +71,7 @@ MidiDriver_CoreMIDI::MidiDriver_CoreMIDI()
: mClient(0), mOutPort(0), mDest(0) {
OSStatus err;
err = MIDIClientCreate(CFSTR("ScummVM MIDI Driver for OS X"), NULL, NULL, &mClient);
err = MIDIClientCreate(CFSTR("Residual MIDI Driver for OS X"), NULL, NULL, &mClient);
}
MidiDriver_CoreMIDI::~MidiDriver_CoreMIDI() {
@ -75,7 +81,7 @@ MidiDriver_CoreMIDI::~MidiDriver_CoreMIDI() {
}
int MidiDriver_CoreMIDI::open() {
if (mDest)
if (isOpen())
return MERR_ALREADY_OPEN;
OSStatus err = noErr;
@ -86,7 +92,7 @@ int MidiDriver_CoreMIDI::open() {
if (dests > 0 && mClient) {
mDest = MIDIGetDestination(0);
err = MIDIOutputPortCreate( mClient,
CFSTR("scummvm_output_port"),
CFSTR("residual_output_port"),
&mOutPort);
} else {
return MERR_DEVICE_NOT_AVAILABLE;
@ -101,7 +107,7 @@ int MidiDriver_CoreMIDI::open() {
void MidiDriver_CoreMIDI::close() {
MidiDriver_MPU401::close();
if (mOutPort && mDest) {
if (isOpen()) {
MIDIPortDispose(mOutPort);
mOutPort = 0;
mDest = 0;
@ -109,8 +115,7 @@ void MidiDriver_CoreMIDI::close() {
}
void MidiDriver_CoreMIDI::send(uint32 b) {
assert(mOutPort != 0);
assert(mDest != 0);
assert(isOpen());
// Extract the MIDI data
byte status_byte = (b & 0x000000FF);
@ -153,8 +158,7 @@ void MidiDriver_CoreMIDI::send(uint32 b) {
}
void MidiDriver_CoreMIDI::sysEx(const byte *msg, uint16 length) {
assert(mOutPort != 0);
assert(mDest != 0);
assert(isOpen());
byte buf[384];
MIDIPacketList *packetList = (MIDIPacketList *)buf;

View File

@ -27,13 +27,18 @@
* some code liberated from seq.cpp and coremidi.cpp
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/sys.h"
#if defined(IRIX)
#include "common/sys.h"
#include "common/util.h"
#include "common/config-manager.h"
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include <dmedia/midi.h>
#include <sys/types.h>
@ -52,6 +57,7 @@ class MidiDriver_DMEDIA : public MidiDriver_MPU401 {
public:
MidiDriver_DMEDIA();
int open();
bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@ -87,8 +93,8 @@ int MidiDriver_DMEDIA::open() {
return -1;
}
if (getenv("SCUMMVM_MIDIPORT")) {
_deviceNum = atoi(getenv("SCUMMVM_MIDIPORT"));
if (getenv("RESIDUAL_MIDIPORT")) {
_deviceNum = atoi(getenv("RESIDUAL_MIDIPORT"));
_midiportName = mdGetName(_deviceNum);
} else {
var = ConfMan.get("dmedia_port").c_str();
@ -174,7 +180,7 @@ void MidiDriver_DMEDIA::sysEx (const byte *msg, uint16 length) {
memcpy(buf, msg, length);
buf[length] = MD_EOX;
event.sysexmsg = buf;
event.msglen = length;
event.msglen = length;
event.msg[0] = MD_SYSEX;
event.msg[1] = 0;
event.msg[2] = 0;

View File

@ -28,16 +28,20 @@
* both the QuickTime support and (vkeybd http://www.alsa-project.org/~iwai/alsa.html)
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/sys.h"
#if defined(USE_SEQ_MIDI)
#include "common/util.h"
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
////////////////////////////////////////
//
@ -51,6 +55,7 @@ class MidiDriver_SEQ : public MidiDriver_MPU401 {
public:
MidiDriver_SEQ();
int open();
bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@ -75,14 +80,14 @@ int MidiDriver_SEQ::open() {
_isOpen = true;
device = 0;
device_name = getenv("SCUMMVM_MIDI");
device_name = getenv("RESIDUAL_MIDI");
if (device_name == NULL) {
warning("SCUMMVM_MIDI environment variable not set, using /dev/sequencer");
warning("RESIDUAL_MIDI environment variable not set, using /dev/sequencer");
device_name = dev_seq;
}
device = (::open((device_name), O_RDWR, 0));
device = ::open((device_name), O_RDWR, 0);
if ((device_name == NULL) || (device < 0)) {
if (device_name == NULL)
@ -95,8 +100,8 @@ int MidiDriver_SEQ::open() {
error("Cannot open /dev/null to dump midi output");
}
if (getenv("SCUMMVM_MIDIPORT"))
_device_num = atoi(getenv("SCUMMVM_MIDIPORT"));
if (getenv("RESIDUAL_MIDIPORT"))
_device_num = atoi(getenv("RESIDUAL_MIDIPORT"));
return 0;
}
@ -144,10 +149,11 @@ void MidiDriver_SEQ::send(uint32 b) {
warning("MidiDriver_SEQ::send: unknown : %08x", (int)b);
break;
}
(void)write(device, buf, position);
if (write(device, buf, position) == -1)
warning("MidiDriver_SEQ::send: write failed (%s)", strerror(errno));
}
void MidiDriver_SEQ::sysEx (const byte *msg, uint16 length) {
void MidiDriver_SEQ::sysEx(const byte *msg, uint16 length) {
unsigned char buf [266*4];
int position = 0;
const byte *chr = msg;
@ -169,7 +175,8 @@ void MidiDriver_SEQ::sysEx (const byte *msg, uint16 length) {
buf[position++] = _device_num;
buf[position++] = 0;
(void)write(device, buf, position);
if (write(device, buf, position) == -1)
warning("MidiDriver_SEQ::send: write failed (%s)", strerror(errno));
}

View File

@ -34,17 +34,23 @@
* 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/sys.h"
#if defined __MINT__
#include <osbind.h>
#include "sound/mpu401.h"
#include "audio/mpu401.h"
#include "common/util.h"
#include "sound/musicplugin.h"
#include "audio/musicplugin.h"
class MidiDriver_STMIDI : public MidiDriver_MPU401 {
public:
MidiDriver_STMIDI() : _isOpen (false) { }
MidiDriver_STMIDI() : _isOpen (false) { }
int open();
bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@ -54,7 +60,7 @@ private:
};
int MidiDriver_STMIDI::open() {
if ((_isOpen) && (!Bcostat(4)))
if (_isOpen && (!Bcostat(4)))
return MERR_ALREADY_OPEN;
warning("ST Midi Port Open");
_isOpen = true;
@ -118,36 +124,36 @@ void MidiDriver_STMIDI::sysEx (const byte *msg, uint16 length) {
class StMidiMusicPlugin : public MusicPluginObject {
public:
const char *getName() const {
return "STMIDI";
}
const char *getName() const {
return "STMIDI";
}
const char *getId() const {
return "stmidi";
}
const char *getId() const {
return "stmidi";
}
MusicDevices getDevices() const;
Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
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;
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();
*mididriver = new MidiDriver_STMIDI();
return Common::kNoError;
return Common::kNoError;
}
//#if PLUGIN_ENABLED_DYNAMIC(STMIDI)
//REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#else
REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#endif
#endif

View File

@ -34,13 +34,18 @@
*
*/
#if defined (UNIX)
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/sys.h"
#if defined(USE_TIMIDITY)
#include "common/util.h"
#include "common/endian.h"
#include "common/str.h"
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include <fcntl.h>
#include <unistd.h>
@ -87,49 +92,50 @@ class MidiDriver_TIMIDITY : public MidiDriver_MPU401 {
public:
MidiDriver_TIMIDITY();
int open();
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
int open();
bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
private:
/* standart routine to extract ip address from a string */
in_addr_t host_to_addr(const char* address);
in_addr_t host_to_addr(const char* address);
/* creates a tcp connection to TiMidity server, returns filedesc (like open()) */
int connect_to_server(const char* hostname, unsigned short tcp_port);
int connect_to_server(const char* hostname, unsigned short tcp_port);
/* send command to the server; printf-like; returns reply string */
char *timidity_ctl_command(const char *fmt, ...) GCC_PRINTF(2, 3);
char *timidity_ctl_command(const char *fmt, ...) GCC_PRINTF(2, 3);
/* timidity data socket-related stuff */
void timidity_meta_seq(int p1, int p2, int p3);
int timidity_sync(int centsec);
int timidity_eot();
void timidity_meta_seq(int p1, int p2, int p3);
int timidity_sync(int centsec);
int timidity_eot();
/* write() analogue for any midi data */
void timidity_write_data(const void *buf, size_t nbytes);
void timidity_write_data(const void *buf, size_t nbytes);
/* get single line of server reply on control connection */
int fdgets(char *buff, size_t buff_size);
int fdgets(char *buff, size_t buff_size);
/* teardown connection to server */
void teardown();
void teardown();
/* close (if needed) and nullify both control and data filedescs */
void close_all();
void close_all();
private:
bool _isOpen;
int _device_num;
bool _isOpen;
int _device_num;
int _control_fd;
int _data_fd;
int _control_fd;
int _data_fd;
/* buffer for partial data read from _control_fd - from timidity-io.c, see fdgets() */
char _controlbuffer[BUFSIZ];
int _controlbuffer_count; /* beginning of read pointer */
int _controlbuffer_size; /* end of read pointer */
char _controlbuffer[BUFSIZ];
int _controlbuffer_count; /* beginning of read pointer */
int _controlbuffer_size; /* end of read pointer */
};
MidiDriver_TIMIDITY::MidiDriver_TIMIDITY() {
@ -144,9 +150,9 @@ MidiDriver_TIMIDITY::MidiDriver_TIMIDITY() {
}
int MidiDriver_TIMIDITY::open() {
char *res;
char timidity_host[MAXHOSTNAMELEN];
int timidity_port, data_port, i;
char *res;
char timidity_host[MAXHOSTNAMELEN];
int timidity_port, data_port, i;
/* count ourselves open */
if (_isOpen)
@ -228,8 +234,8 @@ int MidiDriver_TIMIDITY::open() {
/*
* From seq.cpp
*/
if (getenv("SCUMMVM_MIDIPORT"))
_device_num = atoi(getenv("SCUMMVM_MIDIPORT"));
if (getenv("RESIDUAL_MIDIPORT"))
_device_num = atoi(getenv("RESIDUAL_MIDIPORT"));
return 0;
}
@ -332,7 +338,11 @@ char *MidiDriver_TIMIDITY::timidity_ctl_command(const char *fmt, ...) {
buff[len++] = '\n';
/* write command to control socket */
(void)write(_control_fd, buff, len);
if (write(_control_fd, buff, len) == -1) {
warning("TiMidity: CONTROL WRITE FAILED (%s)", strerror(errno));
// TODO: Disable output?
//close_all();
}
}
while (1) {
@ -418,10 +428,9 @@ void MidiDriver_TIMIDITY::timidity_write_data(const void *buf, size_t nbytes) {
}
int MidiDriver_TIMIDITY::fdgets(char *buff, size_t buff_size) {
int n, len, count, size;
int n, count, size;
char *buff_endp = buff + buff_size - 1, *pbuff, *beg;
len = 0;
count = _controlbuffer_count;
size = _controlbuffer_size;
pbuff = _controlbuffer;

View File

@ -22,6 +22,11 @@
* $Id$
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/sys.h"
#if defined(WIN32) && !defined(_WIN32_WCE)
#define WIN32_LEAN_AND_MEAN
@ -29,8 +34,8 @@
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include "common/config-manager.h"
#include "common/translation.h"
@ -56,6 +61,7 @@ private:
public:
MidiDriver_WIN(int deviceIndex) : _isOpen(false), _device(deviceIndex) { }
int open();
bool isOpen() const { return _isOpen; }
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
@ -88,6 +94,8 @@ void MidiDriver_WIN::close() {
}
void MidiDriver_WIN::send(uint32 b) {
assert(_isOpen);
union {
DWORD dwData;
BYTE bData[4];

Some files were not shown because too many files have changed in this diff Show More