[Scummvm-cvs-logs] SF.net SVN: scummvm:[39397] scummvm/trunk/engines/parallaction

peres001 at users.sourceforge.net peres001 at users.sourceforge.net
Sat Mar 14 18:02:28 CET 2009


Revision: 39397
          http://scummvm.svn.sourceforge.net/scummvm/?rev=39397&view=rev
Author:   peres001
Date:     2009-03-14 17:02:28 +0000 (Sat, 14 Mar 2009)

Log Message:
-----------
Added midi support to BRA. So far music starts, but related script commands haven't been implemented yet.

Modified Paths:
--------------
    scummvm/trunk/engines/parallaction/disk.h
    scummvm/trunk/engines/parallaction/disk_br.cpp
    scummvm/trunk/engines/parallaction/module.mk
    scummvm/trunk/engines/parallaction/parallaction.h
    scummvm/trunk/engines/parallaction/parallaction_br.cpp
    scummvm/trunk/engines/parallaction/parser_br.cpp
    scummvm/trunk/engines/parallaction/sound.h

Added Paths:
-----------
    scummvm/trunk/engines/parallaction/sound_br.cpp

Modified: scummvm/trunk/engines/parallaction/disk.h
===================================================================
--- scummvm/trunk/engines/parallaction/disk.h	2009-03-14 15:43:37 UTC (rev 39396)
+++ scummvm/trunk/engines/parallaction/disk.h	2009-03-14 17:02:28 UTC (rev 39397)
@@ -48,6 +48,9 @@
 struct Cnv;
 struct Sprites;
 struct BackgroundInfo;
+struct GfxObj;
+struct MaskBuffer;
+struct PathBuffer;
 
 class Disk {
 

Modified: scummvm/trunk/engines/parallaction/disk_br.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/disk_br.cpp	2009-03-14 15:43:37 UTC (rev 39396)
+++ scummvm/trunk/engines/parallaction/disk_br.cpp	2009-03-14 17:02:28 UTC (rev 39397)
@@ -395,7 +395,7 @@
 
 Common::SeekableReadStream* DosDisk_br::loadMusic(const char* name) {
 	debugC(5, kDebugDisk, "DosDisk_br::loadMusic");
-	return 0;
+	return openFile("msc/" + Common::String(name), ".msc");
 }
 
 

Modified: scummvm/trunk/engines/parallaction/module.mk
===================================================================
--- scummvm/trunk/engines/parallaction/module.mk	2009-03-14 15:43:37 UTC (rev 39396)
+++ scummvm/trunk/engines/parallaction/module.mk	2009-03-14 17:02:28 UTC (rev 39397)
@@ -29,6 +29,7 @@
 	parser_ns.o \
 	saveload.o \
 	sound_ns.o \
+	sound_br.o \
 	staticres.o \
 	walk.o
 

Modified: scummvm/trunk/engines/parallaction/parallaction.h
===================================================================
--- scummvm/trunk/engines/parallaction/parallaction.h	2009-03-14 15:43:37 UTC (rev 39396)
+++ scummvm/trunk/engines/parallaction/parallaction.h	2009-03-14 17:02:28 UTC (rev 39397)
@@ -125,6 +125,7 @@
 class ProgramExec;
 class SoundMan;
 class SoundMan_ns;
+class SoundMan_br;
 
 
 struct Location {
@@ -533,7 +534,8 @@
 private:
 	LocationParser_br		*_locationParser;
 	ProgramParser_br		*_programParser;
-
+	SoundMan_br				*_soundManI;
+	
 	int32		_counters[32];
 	Table		*_countersNames;
 

Modified: scummvm/trunk/engines/parallaction/parallaction_br.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/parallaction_br.cpp	2009-03-14 15:43:37 UTC (rev 39396)
+++ scummvm/trunk/engines/parallaction/parallaction_br.cpp	2009-03-14 17:02:28 UTC (rev 39397)
@@ -45,7 +45,7 @@
 };
 
 Parallaction_br::Parallaction_br(OSystem* syst, const PARALLACTIONGameDescription *gameDesc) : Parallaction(syst, gameDesc),
-	_locationParser(0), _programParser(0) {
+	_locationParser(0), _programParser(0), _soundManI(0) {
 }
 
 Common::Error Parallaction_br::init() {
@@ -53,8 +53,6 @@
 	_screenWidth = 640;
 	_screenHeight = 400;
 
-	SoundManImpl* _soundManI = 0;
-
 	if (getPlatform() == Common::kPlatformPC) {
 		if (getFeatures() & GF_DEMO) {
 			_disk = new DosDemoDisk_br(this);
@@ -62,11 +60,12 @@
 			_disk = new DosDisk_br(this);
 		}
 		_disk->setLanguage(2);					// NOTE: language is now hardcoded to English. Original used command-line parameters.
-		_soundManI = new DummySoundMan();
+		int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
+		MidiDriver *driver = MidiDriver::createMidi(midiDriver);
+		_soundManI = new DosSoundMan_br(this, driver);
 	} else {
 		_disk = new AmigaDisk_br(this);
 		_disk->setLanguage(2);					// NOTE: language is now hardcoded to English. Original used command-line parameters.
-		_soundManI = new DummySoundMan();
 	}
 
 	_disk->init();
@@ -301,6 +300,10 @@
 	doLocationEnterTransition();
 
 	_cmdExec->run(_location._aCommands);
+	
+	// NOTE: music should not started here! 
+	// TODO: implement the music commands which control music execution
+	_soundMan->execute(SC_PLAYMUSIC);
 
 	_engineFlags &= ~kEngineChangeLocation;
 	_newLocationName.clear();

Modified: scummvm/trunk/engines/parallaction/parser_br.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/parser_br.cpp	2009-03-14 15:43:37 UTC (rev 39396)
+++ scummvm/trunk/engines/parallaction/parser_br.cpp	2009-03-14 17:02:28 UTC (rev 39397)
@@ -421,16 +421,13 @@
 
 
 DECLARE_LOCATION_PARSER(sound)  {
-	debugC(7, kDebugParser, "LOCATION_PARSER(sound) ");
-
-//	_soundMan->loadSound(_tokens[1]);
+	warning("SOUND command unexpected when parsing location");
 }
 
 
 DECLARE_LOCATION_PARSER(music)  {
 	debugC(7, kDebugParser, "LOCATION_PARSER(music) ");
-
-//	_soundMan->loadMusic(_tokens[1]);
+	_vm->_soundMan->execute(SC_SETMUSICFILE, _tokens[1]);
 }
 
 DECLARE_LOCATION_PARSER(redundant)  {

Modified: scummvm/trunk/engines/parallaction/sound.h
===================================================================
--- scummvm/trunk/engines/parallaction/sound.h	2009-03-14 15:43:37 UTC (rev 39396)
+++ scummvm/trunk/engines/parallaction/sound.h	2009-03-14 17:02:28 UTC (rev 39397)
@@ -42,7 +42,10 @@
 
 class Parallaction_ns;
 class MidiPlayer;
+class Parallaction_br;
+class MidiPlayer_MSC;
 
+
 class SoundManImpl {
 public:
 	virtual void execute(int command, const char *parm = 0) = 0;
@@ -177,6 +180,32 @@
 	void execute(int command, const char *parm) { }
 };
 
+class SoundMan_br : public SoundManImpl {
+protected:
+	Common::String _musicFile;
+
+	virtual void playMusic() = 0;
+	virtual void stopMusic() = 0;
+	virtual void pause(bool p) = 0;
+
+public:
+	virtual void execute(int command, const char *parm);	
+	void setMusicFile(const char *parm);
+};
+
+class DosSoundMan_br : public SoundMan_br {
+
+	MidiPlayer_MSC	*_midiPlayer;
+
+public:
+	DosSoundMan_br(Parallaction_br *vm, MidiDriver *midiDriver);
+	~DosSoundMan_br();
+	
+	void playMusic();
+	void stopMusic();
+	void pause(bool p);
+};
+
 } // namespace Parallaction
 
 #endif

Added: scummvm/trunk/engines/parallaction/sound_br.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/sound_br.cpp	                        (rev 0)
+++ scummvm/trunk/engines/parallaction/sound_br.cpp	2009-03-14 17:02:28 UTC (rev 39397)
@@ -0,0 +1,462 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sound/mixer.h"
+#include "common/stream.h"
+#include "common/util.h"
+#include "sound/mididrv.h"
+#include "sound/midiparser.h"
+
+#include "parallaction/disk.h"
+#include "parallaction/parallaction.h"
+#include "parallaction/sound.h"
+
+
+namespace Parallaction {
+
+
+/*
+ * List of calls to the original music driver.
+ * 
+ * 
+ * 1 set music buffer segment
+ * 2 set music buffer offset
+ * 3 set music buffer size
+ * 4 play/resume
+ * 5 stop
+ * 6 pause
+ * 7 set channel volume
+ * 8 set byte_11C5A (boolean flag for ??)
+ * 9 toggle fade
+ * 10 set volume
+ * 11 shutdown
+ * 12 get status
+ * 13 set byte_11C4D (used for fade??)
+ * 14 get volume
+ * 15 get X??
+ * 16 get fade flag
+ * 17 set tempo
+ * 18 get tempo
+ * 19 set Y??
+ * 20 get looping flag
+ * 21 toggle looping flag
+ * 22 get version??
+ * 23 get version??
+ * 24 get busy flag
+ */
+
+class MidiParser_MSC : public MidiParser {
+protected:
+	virtual void parseNextEvent(EventInfo &info);
+	virtual bool loadMusic(byte *data, uint32 size);
+
+	uint8  read1(byte *&data) {
+		return *data++;
+	}
+
+	void parseMetaEvent(EventInfo &info);
+	void parseMidiEvent(EventInfo &info);
+
+	bool byte_11C5A;
+	uint8 _beats;
+	uint8 _lastEvent;
+	byte *_trackEnd;
+
+public:
+	MidiParser_MSC() : byte_11C5A(false) {
+	}
+};
+
+void MidiParser_MSC::parseMetaEvent(EventInfo &info) {
+	uint8 type = read1(_position._play_pos);
+	uint8 len = read1(_position._play_pos);
+	info.ext.type = type;
+	info.length = len;
+	info.ext.data = 0;
+
+	if (type == 0x51) {
+		info.ext.data = _position._play_pos;
+	} else {
+		warning("unknown meta event 0x%02X\n", type);
+		info.ext.type = 0;
+	}
+
+	_position._play_pos += len;
+}
+
+void MidiParser_MSC::parseMidiEvent(EventInfo &info) {
+	uint8 type = info.command();
+
+	switch (type) {
+	case 0x8:
+	case 0x9:
+	case 0xA:
+	case 0xB:
+	case 0xE:
+		info.basic.param1 = read1(_position._play_pos);
+		info.basic.param2 = read1(_position._play_pos);
+		break;
+
+	case 0xC:
+	case 0xD:
+		info.basic.param1 = read1(_position._play_pos);
+		info.basic.param2 = 0;
+		break;
+
+	default:
+		warning("Unexpected midi event 0x%02X in midi data.", info.event);
+	}
+
+	//if ((type == 0xB) && (info.basic.param1 == 64)) info.basic.param2 = 127;
+
+}
+
+void MidiParser_MSC::parseNextEvent(EventInfo &info) {
+	info.start = _position._play_pos;
+
+	if (_position._play_pos >= _trackEnd) {
+		// fake an end-of-track meta event
+		info.delta = 0;
+		info.event = 0xFF;
+		info.ext.type = 0x2F;
+		info.length = 0;
+		return;
+	}
+
+	info.delta = readVLQ(_position._play_pos);
+	info.event = read1(_position._play_pos);
+
+	if (info.event == 0xFF) {
+		parseMetaEvent(info);
+		return;
+	}
+
+	if (info.event < 0x80) {
+		_position._play_pos--;
+		info.event = _lastEvent;
+	}
+
+	parseMidiEvent(info);
+	_lastEvent = info.event;
+
+}
+
+bool MidiParser_MSC::loadMusic(byte *data, uint32 size) {
+	unloadMusic();
+
+	byte *pos = data;
+
+	uint32 signature = read4high(pos);
+	if (memcmp("tCSM", &signature, 4)) {
+		warning("Expected header not found in music file.");
+		return false;
+	}
+
+	_beats = read1(pos);
+	_ppqn = read2low(pos);
+
+	if (byte_11C5A) {
+		// do something with byte_11C4D
+	}
+
+	_lastEvent = 0;
+	_trackEnd = data + size;
+
+	_num_tracks = 1;
+	_tracks[0] = pos;
+
+	setTempo(500000);
+	setTrack(0);
+	return true;
+}
+
+
+MidiParser *createParser_MSC() {
+	return new MidiParser_MSC;
+}
+
+
+class MidiPlayer_MSC : public MidiDriver {
+public:
+
+	enum {
+		NUM_CHANNELS = 16
+	};
+
+	MidiPlayer_MSC(MidiDriver *driver);
+	~MidiPlayer_MSC();
+
+	void play(Common::SeekableReadStream *stream);
+	void stop();
+	void pause(bool p);
+	void updateTimer();
+	void adjustVolume(int diff);
+	void setVolume(int volume);
+	int getVolume() const { return _masterVolume; }
+	void setLooping(bool loop) { _isLooping = loop; }
+
+	// MidiDriver interface
+	int open();
+	void close();
+	void send(uint32 b);
+	void metaEvent(byte type, byte *data, uint16 length);
+	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
+	uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
+	MidiChannel *allocateChannel() { return 0; }
+	MidiChannel *getPercussionChannel() { return 0; }
+
+private:
+
+	static void timerCallback(void *p);
+	void setVolumeInternal(int volume);
+
+	Common::Mutex _mutex;
+	MidiDriver *_driver;
+	MidiParser *_parser;
+	uint8 *_midiData;
+	bool _isLooping;
+	bool _isPlaying;
+	bool _paused;
+
+	int _masterVolume;
+	MidiChannel *_channels[NUM_CHANNELS];
+	uint8 _volume[NUM_CHANNELS];
+};
+
+
+
+MidiPlayer_MSC::MidiPlayer_MSC(MidiDriver *driver)
+	: _driver(driver), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _paused(false), _masterVolume(0) {
+	assert(_driver);
+	memset(_channels, 0, sizeof(_channels));
+	for (int i = 0; i < NUM_CHANNELS; i++) {
+		_volume[i] = 127;
+	}
+
+	open();
+}
+
+MidiPlayer_MSC::~MidiPlayer_MSC() {
+	close();
+}
+
+void MidiPlayer_MSC::play(Common::SeekableReadStream *stream) {
+	if (!stream) {
+		stop();
+		return;
+	}
+
+	int size = stream->size();
+
+	_midiData = (uint8 *)malloc(size);
+	if (_midiData) {
+		stream->read(_midiData, size);
+		delete stream;
+		_mutex.lock();
+		_parser->loadMusic(_midiData, size);
+		_parser->setTrack(0);
+		_isLooping = true;
+		_isPlaying = true;
+		_mutex.unlock();
+	}
+}
+
+void MidiPlayer_MSC::stop() {
+	_mutex.lock();
+	if (_isPlaying) {
+		_isPlaying = false;
+		_parser->unloadMusic();
+		free(_midiData);
+		_midiData = 0;
+	}
+	_mutex.unlock();
+}
+
+void MidiPlayer_MSC::pause(bool p) {
+	_paused = p;
+	setVolumeInternal(_paused ? 0 : _masterVolume);
+}
+
+void MidiPlayer_MSC::updateTimer() {
+	if (_paused) {
+		return;
+	}
+
+	Common::StackLock lock(_mutex);
+	if (_isPlaying) {
+		_parser->onTimer();
+	}
+}
+
+void MidiPlayer_MSC::adjustVolume(int diff) {
+	setVolume(_masterVolume + diff);
+}
+
+void MidiPlayer_MSC::setVolume(int volume) {
+	_masterVolume = CLIP(volume, 0, 255);
+	setVolumeInternal(_masterVolume);
+}
+
+void MidiPlayer_MSC::setVolumeInternal(int volume) {
+	Common::StackLock lock(_mutex);
+	for (int i = 0; i < NUM_CHANNELS; ++i) {
+		if (_channels[i]) {
+			_channels[i]->volume(_volume[i] * volume / 255);
+		}
+	}
+}
+
+int MidiPlayer_MSC::open() {
+	int ret = _driver->open();
+	if (ret == 0) {
+		_parser = createParser_MSC();
+		_parser->setMidiDriver(this);
+		_parser->setTimerRate(_driver->getBaseTempo());
+		_driver->setTimerCallback(this, &timerCallback);
+	}
+	return ret;
+}
+
+void MidiPlayer_MSC::close() {
+	stop();
+	_mutex.lock();
+	_driver->setTimerCallback(NULL, NULL);
+	_driver->close();
+	delete _driver;
+	_driver = 0;
+	_parser->setMidiDriver(NULL);
+	delete _parser;
+	_mutex.unlock();
+}
+
+void MidiPlayer_MSC::send(uint32 b) {
+	const byte ch = b & 0x0F;
+	byte param2 = (b >> 16) & 0xFF;
+
+	switch (b & 0xFFF0) {
+	case 0x07B0: // volume change
+		_volume[ch] = param2;
+		break;
+	}
+
+	if (!_channels[ch]) {
+		_channels[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+	}
+	if (_channels[ch]) {
+		_channels[ch]->send(b);
+	}
+}
+
+void MidiPlayer_MSC::metaEvent(byte type, byte *data, uint16 length) {
+	switch (type) {
+	case 0x2F: // end of Track
+		if (_isLooping) {
+			_parser->jumpToTick(0);
+		} else {
+			stop();
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+void MidiPlayer_MSC::timerCallback(void *p) {
+	MidiPlayer_MSC *player = (MidiPlayer_MSC *)p;
+
+	player->updateTimer();
+}
+
+DosSoundMan_br::DosSoundMan_br(Parallaction_br *vm, MidiDriver *driver) {
+	_midiPlayer = new MidiPlayer_MSC(driver);
+	assert(_midiPlayer);
+}
+
+DosSoundMan_br::~DosSoundMan_br() {
+	delete _midiPlayer;
+}
+	
+void DosSoundMan_br::playMusic() {
+	if (_musicFile.empty()) {
+		return;
+	}
+	
+	Common::SeekableReadStream *s = _vm->_disk->loadMusic(_musicFile.c_str());
+	assert(s);
+	_midiPlayer->play(s);
+}
+
+void DosSoundMan_br::stopMusic() {
+	_midiPlayer->stop();
+}
+
+void DosSoundMan_br::pause(bool p) {
+	_midiPlayer->pause(p);
+}
+
+void SoundMan_br::setMusicFile(const char *name) {
+	_musicFile = name;
+}
+
+void SoundMan_br::execute(int command, const char *parm) {	
+	uint32 n = parm ? strtoul(parm, 0, 10) : 0;
+	bool b = (n == 1) ? true : false;
+	
+	switch (command) {
+	case SC_PLAYMUSIC:
+		playMusic();
+		break;
+	case SC_STOPMUSIC:
+		stopMusic();
+		break;
+	case SC_SETMUSICFILE:
+		setMusicFile(parm);
+		break;
+	
+	case SC_PLAYSFX:
+		warning("SC_PLAYSFX not yet supported!");
+		break;	
+	case SC_STOPSFX:
+		warning("SC_STOPSFX not yet supported!");
+		break;
+	
+	case SC_SETSFXCHANNEL:
+		warning("SC_SETSFXCHANNEL not yet supported!");
+		break;
+	case SC_SETSFXLOOPING:
+		warning("SC_SETSFXLOOPING not yet supported!");
+		break;
+	case SC_SETSFXVOLUME:
+		warning("SC_SETSFXVOLUME not yet supported!");
+		break;
+	
+	case SC_PAUSE:
+		pause(b);
+		break;
+	}
+}
+
+
+} // namespace Parallaction


Property changes on: scummvm/trunk/engines/parallaction/sound_br.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list