[Scummvm-cvs-logs] SF.net SVN: scummvm: [29552] scummvm/trunk/engines/igor

cyx at users.sourceforge.net cyx at users.sourceforge.net
Sun Nov 18 07:25:23 CET 2007


Revision: 29552
          http://scummvm.svn.sourceforge.net/scummvm/?rev=29552&view=rev
Author:   cyx
Date:     2007-11-17 22:25:23 -0800 (Sat, 17 Nov 2007)

Log Message:
-----------
- added CTMF music support
- fixed dialogue in PART12

Modified Paths:
--------------
    scummvm/trunk/engines/igor/igor.cpp
    scummvm/trunk/engines/igor/igor.h
    scummvm/trunk/engines/igor/menu.cpp
    scummvm/trunk/engines/igor/module.mk
    scummvm/trunk/engines/igor/parts/part_12.cpp
    scummvm/trunk/engines/igor/parts/part_13.cpp
    scummvm/trunk/engines/igor/parts/part_14.cpp
    scummvm/trunk/engines/igor/parts/part_16.cpp
    scummvm/trunk/engines/igor/parts/part_17.cpp
    scummvm/trunk/engines/igor/parts/part_95.cpp
    scummvm/trunk/engines/igor/parts/part_main.cpp

Added Paths:
-----------
    scummvm/trunk/engines/igor/midi.cpp
    scummvm/trunk/engines/igor/midi.h

Modified: scummvm/trunk/engines/igor/igor.cpp
===================================================================
--- scummvm/trunk/engines/igor/igor.cpp	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/igor.cpp	2007-11-18 06:25:23 UTC (rev 29552)
@@ -32,12 +32,15 @@
 #include "sound/voc.h"
 
 #include "igor/igor.h"
+#include "igor/midi.h"
 
 namespace Igor {
 
 IgorEngine::IgorEngine(OSystem *system, int gameVersion)
 	: Engine(system), _gameVersion(gameVersion) {
 
+	_midiPlayer = new MidiPlayer(this);
+
 	_screenVGA = (uint8 *)malloc(320 * 200);
 	for (int i = 0; i < 4; ++i) {
 		_facingIgorFrames[i] = (uint8 *)malloc(13500);
@@ -60,6 +63,7 @@
 }
 
 IgorEngine::~IgorEngine() {
+	delete _midiPlayer;
 	Common::clearAllSpecialDebugLevels();
 	free(_screenVGA);
 	for (int i = 0; i < 4; ++i) {
@@ -332,14 +336,15 @@
 	}
 	if (seq) {
 		for (int i = 0; i < 5; ++i) {
-			free(_musicSequenceTable[i]);
+			free(_musicSequenceTable[i].data);
 		}
 		for (int i = 0; seq[i]; ++i) {
-			_musicSequenceTable[i] = loadData(seq[i]);
+			_musicSequenceTable[i].data = loadData(seq[i], 0, &_musicSequenceTable[i].dataSize);
 		}
 	}
 	_gameState.musicNum = num;
 	_gameState.musicSequenceIndex = 1;
+	_midiPlayer->playMusic(_musicSequenceTable[0].data, _musicSequenceTable[0].dataSize);
 }
 
 void IgorEngine::updateMusic() {
@@ -825,6 +830,8 @@
 				decodeRoomString(src, _dialogueQuestions[i][n], len);
 				_dialogueQuestions[i][n][len] = '\0';
 				debugC(9, kDebugResource, "loadDialogueData() _dialogueQuestions[%d][%d] '%s'", i, n, _dialogueQuestions[i][n]);
+			} else {
+				_dialogueQuestions[i][n][0] = '\0';
 			}
 		}
 	}
@@ -836,6 +843,8 @@
 			decodeRoomString(src, _dialogueReplies[i], len);
 			_dialogueReplies[i][len] = '\0';
 			debugC(9, kDebugResource, "loadDialogueData() _dialogueReplies[%d] '%s'", i, _dialogueReplies[i]);
+		} else {
+			_dialogueReplies[i][0] = '\0';
 		}
 	}
 	free(p);
@@ -1588,6 +1597,9 @@
 }
 
 void IgorEngine::animateIgorTalking(int frame) {
+	if (getPart() == 4) {
+		return;
+	}
 	if (getPart() == 85) {
 		PART_85_HELPER_6(frame);
 		return;
@@ -2792,13 +2804,14 @@
 	_gameState.dialogueChoiceStart = 1;
 	_gameState.dialogueChoiceCount = 1;
 	_dialogueEnded = false;
+	if (getPart() == 12 && _objectsState[44] == 0) {
+		_gameState.dialogueData[6] = 1;
+		dialogueReplyToQuestion(x, y, r, g, b, 40);
+	}
 	do {
 		if (getPart() == 15 && _objectsState[48] == 0) {
 			_gameState.dialogueData[6] = 0;
 		}
-		if (getPart() == 12 && _objectsState[44] == 0) {
-			_gameState.dialogueData[6] = 1;
-		}
 		drawDialogueChoices();
 		(this->*_updateDialogue)(kUpdateDialogueAnimStanding);
 		_dialogueChoiceSelected = selectDialogue();
@@ -2922,14 +2935,16 @@
 	waitForEndOfIgorDialogue();
 }
 
-void IgorEngine::dialogueReplyToQuestion(int x, int y, int r, int g, int b) {
-	int offset = (_dialogueInfo[_dialogueChoiceSelected] - 1) * 6 + (_gameState.dialogueChoiceCount - 1) * 30 + (_gameState.dialogueChoiceStart - 1) * _roomDataOffsets.dlg.matSize;
-	int reply = _gameState.dialogueData[offset + 4];
-	debugC(9, kDebugEngine, "dialogueReplyToQuestion() dialogue choice %d reply %d", _dialogueChoiceSelected, reply);
+void IgorEngine::dialogueReplyToQuestion(int x, int y, int r, int g, int b, int reply) {
 	if (reply == 0) {
-		return;
+		int offset = (_dialogueInfo[_dialogueChoiceSelected] - 1) * 6 + (_gameState.dialogueChoiceCount - 1) * 30 + (_gameState.dialogueChoiceStart - 1) * _roomDataOffsets.dlg.matSize;
+		reply = _gameState.dialogueData[offset + 4];
+		debugC(9, kDebugEngine, "dialogueReplyToQuestion() dialogue choice %d reply %d", _dialogueChoiceSelected, reply);
+		if (reply == 0) {
+			return;
+		}
 	}
-	offset = _roomDataOffsets.dlg.matSize * 3 + reply;
+	int offset = 30 + _roomDataOffsets.dlg.matSize + reply;
 	int count = _gameState.dialogueData[offset - 1];
 	int dialogueIndex = 250;
 	for (int i = 0; i < count; ++i) {

Modified: scummvm/trunk/engines/igor/igor.h
===================================================================
--- scummvm/trunk/engines/igor/igor.h	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/igor.h	2007-11-18 06:25:23 UTC (rev 29552)
@@ -265,6 +265,7 @@
 };
 
 class TypeSerializer;
+class MidiPlayer;
 
 class IgorEngine: public Engine {
 public:
@@ -390,13 +391,15 @@
 	void drawDialogueChoices();
 	int selectDialogue();
 	void dialogueAskQuestion();
-	void dialogueReplyToQuestion(int x, int y, int r, int g, int b);
+	void dialogueReplyToQuestion(int x, int y, int r, int g, int b, int reply = 0);
 
 	void saveOrLoadGameState(TypeSerializer &typeSerializer);
 	void loadGameState(int slot);
 	void saveGameState(int slot);
 	void generateGameStateFileName(int num, char *dst, int len) const;
 
+	MidiPlayer *_midiPlayer;
+
 	Common::File _ovlFile;
 	Common::File _sndFile;
 	Common::File _tblFile;
@@ -465,7 +468,10 @@
 	ExecuteActionProc _executeMainAction;
 	ExecuteActionProc _executeRoomAction;
 	uint8 _previousMusic;
-	uint8 *_musicSequenceTable[5];
+	struct {
+		uint8 *data;
+		int dataSize;
+	} _musicSequenceTable[5];
 	Action _currentAction;
 	uint8 _actionCode;
 	uint8 _actionWalkPoint;
@@ -571,7 +577,7 @@
 	void PART_12_ACTION_105();
 	void PART_12_ACTION_108();
 	void PART_12_UPDATE_ROOM_BACKGROUND();
-	void PART_12_UPDATE_DIALOGUE_TOBIAS(int action);
+	void PART_12_UPDATE_DIALOGUE_CHURCHMAN(int action);
 	void PART_12_HANDLE_DIALOGUE_CHURCHMAN();
 	void PART_12_HELPER_1(int num);
 	void PART_12_HELPER_2();

Modified: scummvm/trunk/engines/igor/menu.cpp
===================================================================
--- scummvm/trunk/engines/igor/menu.cpp	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/menu.cpp	2007-11-18 06:25:23 UTC (rev 29552)
@@ -333,11 +333,6 @@
 		_system->updateScreen();
 		_system->delayMillis(1000 / 60);
 	}
-	if (!_eventQuitGame && _currentPart == kInvalidPart) {
-		if (_gameVersion == kIdEngDemo100 || _gameVersion == kIdEngDemo110) {
-			_currentPart = kSharewarePart;
-		}
-	}
 	showCursor();
 }
 

Added: scummvm/trunk/engines/igor/midi.cpp
===================================================================
--- scummvm/trunk/engines/igor/midi.cpp	                        (rev 0)
+++ scummvm/trunk/engines/igor/midi.cpp	2007-11-18 06:25:23 UTC (rev 29552)
@@ -0,0 +1,362 @@
+/* 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 "igor/igor.h"
+#include "igor/midi.h"
+
+namespace Igor {
+
+MidiParser_CTMF::MidiParser_CTMF()
+	: _instrumentsCount(0) {
+	memset(_instruments, 0, sizeof(_instruments));
+}
+
+void MidiParser_CTMF::decodeHeader(const uint8 *p) {
+	_instrumentsDataOffset = READ_LE_UINT16(p); p += 2;
+	_midiDataOffset = READ_LE_UINT16(p); p += 2;
+	_ticksPerQuarter = READ_LE_UINT16(p); p += 2;
+	_ticksPerSecond = READ_LE_UINT16(p); p += 2;
+	p += 22;
+	_instrumentsCount = READ_LE_UINT16(p); p += 2;
+	_basicTempo = READ_LE_UINT16(p); p += 2;
+}
+
+void MidiParser_CTMF::decodeAdlibInstrument(struct AdlibInstrument *ins, const uint8 *p) {
+	ins->chr[kAdlibCarrier] = p[0];
+	ins->chr[kAdlibModulator] = p[1];
+	ins->scale[kAdlibCarrier] = p[2];
+	ins->scale[kAdlibModulator] = p[3];
+	ins->attack[kAdlibCarrier] = p[4];
+	ins->attack[kAdlibModulator] = p[5];
+	ins->sustain[kAdlibCarrier] = p[6];
+	ins->sustain[kAdlibModulator] = p[7];
+	ins->waveSel[kAdlibCarrier] = p[8];
+	ins->waveSel[kAdlibModulator] = p[9];
+	ins->feedback = p[10];
+}
+
+bool MidiParser_CTMF::loadMusic(byte *data, uint32 size) {
+	if (memcmp(data, "CTMF", 4) == 0 && READ_LE_UINT16(data + 4) == 0x101) {
+		decodeHeader(data + 6);
+		assert(_instrumentsCount <= kMaxInstruments);
+		for (int i = 0; i < _instrumentsCount; ++i) {
+			decodeAdlibInstrument(&_instruments[i], data + _instrumentsDataOffset + i * 16);
+		}
+		// reset parser
+		_num_tracks = 1;
+		_tracks[0] = data + _midiDataOffset;
+		_ppqn = _ticksPerQuarter;
+		setTempo(500000);
+		setTrack(0);
+		return true;
+	}
+	return false;
+}
+
+void MidiParser_CTMF::parseNextEvent(EventInfo &info) {
+	info.start = _position._play_pos;
+	info.delta = readVLQ(_position._play_pos);
+
+	if ((_position._play_pos[0] & 0xF0) >= 0x80) {
+		info.event = *_position._play_pos++;
+	} else {
+		info.event = _position._running_status;
+	}
+
+	if ((info.event & 0x80) == 0) {
+		return;
+	}
+
+	_position._running_status = info.event;
+	switch (info.command()) {
+	case 0x8: // Note Off
+	case 0x9: // Note On
+	case 0xB: // Control Mode Change
+		info.basic.param1 = *_position._play_pos++;
+		info.basic.param2 = *_position._play_pos++;
+		if (info.command() == 0x9 && info.basic.param2 == 0) {
+			info.event = info.channel() | 0x80; // Note Off
+		}
+		return;
+	case 0xC: // Program Change
+		info.basic.param1 = *(_position._play_pos++);
+		info.basic.param2 = 0;
+		return;
+	case 0xF:
+		switch (info.event & 15) {
+		case 0xF:
+			info.ext.type = *(_position._play_pos++);
+			info.length = readVLQ(_position._play_pos);
+			info.ext.data = _position._play_pos;
+			_position._play_pos += info.length;
+			return;
+		}
+	}
+	warning("MidiParser_CTMF::parseNextEvent: Unhandled event code %x", info.event);
+}
+
+int AdlibMidiDriver::open() {
+	MidiDriver_Emulated::open();
+	_opl = makeAdlibOPL(getRate());
+	memset(_adlibData, 0, sizeof(_adlibData));
+	_adlibRhythmMode = false;
+	for (int i = 0; i < kAdlibChannelsCount; ++i) {
+		_adlibChannels[i].ch = -1;
+		_adlibChannels[i].lt = _adlibChannels[i].note = 0;
+	}
+	memset(_adlibInstrumentsMappingTable, 0, sizeof(_adlibInstrumentsMappingTable));
+	adlibSetupCard();
+	_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
+	return 0;
+}
+
+void AdlibMidiDriver::close() {
+	_mixer->stopHandle(_mixerSoundHandle);
+	OPLDestroy(_opl);
+}
+
+void AdlibMidiDriver::send(uint32 b) {
+	int channel = b & 15;
+	int cmd = (b >> 4) & 7;
+	int param1 = (b >> 8) & 255;
+	int param2 = (b >> 16) & 255;
+	switch (cmd) {
+	case 0:
+		adlibTurnNoteOff(channel, param1);
+		break;
+	case 1:
+		adlibTurnNoteOn(channel, param1, param2);
+		break;
+	case 3:
+		adlibControlChange(channel, param1, param2);
+		break;
+	case 4:
+		adlibProgramChange(channel, param1);
+		break;
+	default:
+		warning("Unhandled cmd %d channel %d (0x%X)", cmd, channel, b);
+		break;
+	}
+}
+
+void AdlibMidiDriver::generateSamples(int16 *data, int len) {
+	memset(data, 0, sizeof(int16) * len);
+	YM3812UpdateOne(_opl, data, len);
+}
+
+void AdlibMidiDriver::adlibWrite(int port, int value) {
+	OPLWriteReg(_opl, port, value);
+	_adlibData[port & 255] = value & 255;
+}
+
+void AdlibMidiDriver::adlibSetupCard() {
+	for (int i = 0; i < 256; ++i) {
+		adlibWrite(i, 0);
+	}
+	adlibWrite(1, 0x20);
+	adlibWrite(0xBD, 0xC0);
+}
+
+void AdlibMidiDriver::adlibTurnNoteOff(int channel, int note) {
+	for (int i = 0; i < kAdlibChannelsCount; ++i) {
+		if (_adlibChannels[i].ch == channel && _adlibChannels[i].note == note) {
+			adlibEndNote(i);
+			_adlibChannels[i].ch = -1;
+		}
+	}
+}
+
+void AdlibMidiDriver::adlibTurnNoteOn(int channel, int note, int velocity) {
+	assert(velocity != 0);
+
+	for (int i = 0; i < kAdlibChannelsCount; ++i) {
+		if (_adlibChannels[i].ch != -1) {
+			++_adlibChannels[i].lt;
+		}
+	}
+
+	int ch = -1;
+	if (!_adlibRhythmMode || channel < 11) {
+		int maxLt = -1;
+		int maxCh = -1;
+		for (int i = 0; i < (_adlibRhythmMode ? 6 : 9); ++i) {
+			if (_adlibChannels[i].ch == -1) {
+				ch = i;
+				break;
+			}
+			if (_adlibChannels[i].lt > maxLt) {
+				maxLt = _adlibChannels[i].lt;
+				maxCh = i;
+			}
+		}
+		if (ch == -1) {
+			assert(maxCh != -1);
+			ch = maxCh;
+			adlibEndNote(ch);
+		}
+	} else {
+		ch = _adlibPercussionsMappingTable[channel - 11];
+	}
+
+	const AdlibInstrument &ins = _adlibInstruments[_adlibInstrumentsMappingTable[channel]];
+	if (!_adlibRhythmMode || channel < 12) {
+		adlibSetupInstrument(ch, ins);
+	} else {
+		adlibSetupPercussion(channel, ins);
+	}
+	adlibSetupNote(ch, note - 13, velocity);
+	_adlibChannels[ch].ch = channel;
+	_adlibChannels[ch].note = note;
+	_adlibChannels[ch].lt = 0;
+}
+
+void AdlibMidiDriver::adlibSetupInstrument(int channel, const AdlibInstrument &ins) {
+	adlibWrite(0x20 + _adlibOperatorsTable[channel], ins.chr[kAdlibCarrier]);
+	adlibWrite(0x23 + _adlibOperatorsTable[channel], ins.chr[kAdlibModulator]);
+	adlibWrite(0x40 + _adlibOperatorsTable[channel], ins.scale[kAdlibCarrier]);
+	if ((ins.feedback & 1) == 0) {
+		adlibWrite(0x43 + _adlibOperatorsTable[channel], ins.scale[kAdlibModulator]);
+	} else {
+		adlibWrite(0x43 + _adlibOperatorsTable[channel], 0);
+	}
+	adlibWrite(0x60 + _adlibOperatorsTable[channel], ins.attack[kAdlibCarrier]);
+	adlibWrite(0x63 + _adlibOperatorsTable[channel], ins.attack[kAdlibModulator]);
+	adlibWrite(0x80 + _adlibOperatorsTable[channel], ins.sustain[kAdlibCarrier]);
+	adlibWrite(0x83 + _adlibOperatorsTable[channel], ins.sustain[kAdlibModulator]);
+	adlibWrite(0xE0 + _adlibOperatorsTable[channel], ins.waveSel[kAdlibCarrier]);
+	adlibWrite(0xE3 + _adlibOperatorsTable[channel], ins.waveSel[kAdlibModulator]);
+	adlibWrite(0xC0 + channel, ins.feedback);
+}
+
+void AdlibMidiDriver::adlibSetupPercussion(int channel, const AdlibInstrument &ins) {
+	channel = _adlibChannelsMappingTable[channel - 12];
+	adlibWrite(0x20 + channel, ins.chr[kAdlibCarrier]);
+	adlibWrite(0x40 + channel, ins.scale[kAdlibCarrier]);
+	adlibWrite(0x60 + channel, ins.attack[kAdlibCarrier]);
+	adlibWrite(0x80 + channel, ins.sustain[kAdlibCarrier]);
+	adlibWrite(0xE0 + channel, ins.waveSel[kAdlibCarrier]);
+	adlibWrite(0xC0 + channel, ins.feedback);
+}
+
+void AdlibMidiDriver::adlibSetupNote(int channel, int note, int velocity) {
+	adlibSetVolume(channel, velocity);
+	int f = _adlibNoteFreqTable[note % 12];
+	adlibWrite(0xA0 + channel, f);
+	int oct = note / 12;
+	int c = ((f & 0x300) >> 8) + (oct << 2);
+	if (!_adlibRhythmMode || channel < 6) {
+		c |= 0x20;
+	}
+	adlibWrite(0xB0 + channel, c);
+}
+
+void AdlibMidiDriver::adlibEndNote(int channel) {
+	adlibWrite(0xB0 + channel, _adlibData[0xB0 + channel] & ~0x20);
+}
+
+void AdlibMidiDriver::adlibSetVolume(int channel, int volume) {
+	volume = 63 - (volume >> 1);
+	if ((_adlibData[0xC0 + channel] & 1) == 1) {
+		adlibWrite(0x40 + _adlibOperatorsTable[channel], volume | (_adlibData[0x40 + _adlibOperatorsTable[channel]] & 0xC0));
+	}
+	adlibWrite(0x43 + _adlibOperatorsTable[channel], volume | (_adlibData[0x43 + _adlibOperatorsTable[channel]] & 0xC0));
+}
+
+void AdlibMidiDriver::adlibControlChange(int channel, int control, int param) {
+	switch (control) {
+	case 0x67:
+		_adlibRhythmMode = param != 0;
+		if (_adlibRhythmMode) {
+			adlibWrite(0xBD, _adlibData[0xBD] | 0x20);
+		} else {
+			adlibWrite(0xBD, _adlibData[0xBD] & ~0x20);
+		}
+		break;
+	case 0x7B:
+		adlibTurnNoteOff(channel, -1);
+		break;
+	default:
+		warning("Unhandled adlibControlChange 0x%X %d", control, param);
+		break;
+	}
+}
+
+void AdlibMidiDriver::adlibProgramChange(int channel, int num) {
+	_adlibInstrumentsMappingTable[channel] = num;
+}
+
+const uint8 AdlibMidiDriver::_adlibOperatorsTable[] = { 0, 1, 2, 8, 9, 10, 16, 17, 18 };
+
+const uint8 AdlibMidiDriver::_adlibChannelsMappingTable[] = { 20, 18, 21, 17 };
+
+const int16 AdlibMidiDriver::_adlibNoteFreqTable[] = { 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647, 686 };
+
+const uint8 AdlibMidiDriver::_adlibPercussionsMappingTable[] = { 6, 7, 8, 8, 7 };
+
+MidiPlayer::MidiPlayer(IgorEngine *vm) : _isPlaying(false) {
+	_driver = new AdlibMidiDriver(vm->_mixer);
+	_driver->open();
+	_parser = new MidiParser_CTMF;
+	_parser->setMidiDriver(_driver);
+	_parser->setTimerRate(_driver->getBaseTempo());
+	_driver->setTimerCallback(this, &MidiPlayer::updateTimerCallback);
+}
+
+MidiPlayer::~MidiPlayer() {
+	stopMusic();
+	_driver->setTimerCallback(0, 0);
+	_driver->close();
+	delete _parser;
+	delete _driver;
+}
+
+void MidiPlayer::playMusic(uint8 *data, uint32 size) {
+	stopMusic();
+	_mutex.lock();
+	_isPlaying = true;
+	_parser->loadMusic(data, size);
+	_parser->setTrack(0);
+	_driver->setInstruments(&_parser->_instruments[0]);
+	_mutex.unlock();
+}
+
+void MidiPlayer::stopMusic() {
+	_mutex.lock();
+	if (_isPlaying) {
+		_isPlaying = false;
+		_parser->unloadMusic();
+	}
+	_mutex.unlock();
+}
+
+void MidiPlayer::updateTimer() {
+	_mutex.lock();
+	if (_isPlaying) {
+		_parser->onTimer();
+	}
+	_mutex.unlock();
+}
+
+} // namespace Igor


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

Added: scummvm/trunk/engines/igor/midi.h
===================================================================
--- scummvm/trunk/engines/igor/midi.h	                        (rev 0)
+++ scummvm/trunk/engines/igor/midi.h	2007-11-18 06:25:23 UTC (rev 29552)
@@ -0,0 +1,167 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef IGOR_MIDI_H
+#define IGOR_MIDI_H
+
+#include "common/util.h"
+#include "common/mutex.h"
+
+#include "sound/fmopl.h"
+#include "sound/mididrv.h"
+#include "sound/midiparser.h"
+#include "sound/softsynth/emumidi.h"
+
+namespace Igor {
+
+enum {
+	kAdlibCarrier = 0,
+	kAdlibModulator
+};
+
+struct AdlibInstrument {
+	uint8 chr[2];
+	uint8 scale[2];
+	uint8 attack[2];
+	uint8 sustain[2];
+	uint8 waveSel[2];
+	uint8 feedback;
+};
+
+class MidiParser_CTMF : public MidiParser {
+public:
+
+	enum {
+		kMaxInstruments = 16
+	};
+
+	MidiParser_CTMF();
+	~MidiParser_CTMF() {}
+
+	bool loadMusic(byte *data, uint32 size);
+
+	AdlibInstrument _instruments[kMaxInstruments];
+	int _instrumentsCount;
+
+protected:
+
+	void decodeHeader(const uint8 *p);
+	void decodeAdlibInstrument(struct AdlibInstrument *ins, const uint8 *p);
+
+	void parseNextEvent(EventInfo &info);
+
+private:
+
+	int _instrumentsDataOffset;
+	int _midiDataOffset;
+	int _ticksPerQuarter;
+	int _ticksPerSecond;
+	int _basicTempo;
+};
+
+class AdlibMidiDriver : public MidiDriver_Emulated {
+public:
+
+	enum {
+		kAdlibChannelsCount = 18
+	};
+
+	AdlibMidiDriver(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) {}
+	~AdlibMidiDriver() {}
+
+	// MidiDriver
+	int open();
+	void close();
+	void send(uint32 b);
+	void metaEvent(byte type, byte *data, uint16 length) {}
+	void sysEx(const byte *msg, uint16 length) {}
+	MidiChannel *allocateChannel() { return 0; }
+	MidiChannel *getPercussionChannel() { return 0; }
+
+	// AudioStream
+	bool isStereo() const { return false; }
+	int getRate() const { return _mixer->getOutputRate(); }
+
+	// MidiDriver_Emulated
+	void generateSamples(int16 *buf, int len);
+
+	void setInstruments(AdlibInstrument *i) { _adlibInstruments = i; }
+
+private:
+
+	void adlibWrite(int port, int value);
+	void adlibSetupCard();
+	void adlibTurnNoteOff(int channel, int note);
+	void adlibTurnNoteOn(int channel, int note, int velocity);
+	void adlibSetupInstrument(int channel, const AdlibInstrument &ins);
+	void adlibSetupPercussion(int channel, const AdlibInstrument &ins);
+	void adlibSetupNote(int channel, int note, int velocity);
+	void adlibEndNote(int channel);
+	void adlibSetVolume(int channel, int volume);
+	void adlibControlChange(int channel, int control, int param);
+	void adlibProgramChange(int channel, int num);
+
+	FM_OPL *_opl;
+	uint8 _adlibData[256];
+	bool _adlibRhythmMode;
+	struct {
+		int ch;
+		int note;
+		int lt;
+	} _adlibChannels[kAdlibChannelsCount];
+	int _adlibInstrumentsMappingTable[kAdlibChannelsCount];
+	AdlibInstrument *_adlibInstruments;
+
+	static const uint8 _adlibOperatorsTable[];
+	static const uint8 _adlibChannelsMappingTable[];
+	static const int16 _adlibNoteFreqTable[];
+	static const uint8 _adlibPercussionsMappingTable[];
+};
+
+class IgorEngine;
+
+class MidiPlayer {
+public:
+
+	MidiPlayer(IgorEngine *vm);
+	~MidiPlayer();
+
+	void playMusic(uint8 *data, uint32 size);
+	void stopMusic();
+
+private:
+
+	void updateTimer();
+	static void updateTimerCallback(void *p) { ((MidiPlayer *)p)->updateTimer(); }
+
+	MidiParser_CTMF *_parser;
+	AdlibMidiDriver *_driver;
+	Common::Mutex _mutex;
+	bool _isPlaying;
+};
+
+} // namespace Igor
+
+#endif


Property changes on: scummvm/trunk/engines/igor/midi.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Modified: scummvm/trunk/engines/igor/module.mk
===================================================================
--- scummvm/trunk/engines/igor/module.mk	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/module.mk	2007-11-18 06:25:23 UTC (rev 29552)
@@ -4,6 +4,7 @@
 	detection.o \
 	igor.o \
 	menu.o \
+	midi.o \
 	saveload.o \
 	staticres.o \
 	parts/part_04.o \

Modified: scummvm/trunk/engines/igor/parts/part_12.cpp
===================================================================
--- scummvm/trunk/engines/igor/parts/part_12.cpp	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/parts/part_12.cpp	2007-11-18 06:25:23 UTC (rev 29552)
@@ -32,6 +32,7 @@
 static const uint8 PART_12_DATA_ANIM_2[16] = { 0, 1, 2, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 5, 6, 7 };
 
 void IgorEngine::PART_12_EXEC_ACTION(int action) {
+	debugC(9, kDebugGame, "PART_12_EXEC_ACTION %d", action);
 	switch (action) {
 	case 101:
 		PART_12_ACTION_101();
@@ -141,7 +142,7 @@
 	_walkData[0].dxPos = 10;
 	_walkData[0].yPosChanged = 1;
 	_walkData[0].dyPos = 3;
-	_walkData[0].scaleHeight = 1;
+	_walkData[0].scaleHeight = 50;
 	_walkDataCurrentIndex = 0;
 	_walkDataLastIndex = 1;
 	src = _animFramesBuffer + 0x395B + READ_LE_UINT16(_animFramesBuffer + 0xA448) - 1;
@@ -310,7 +311,7 @@
 	}
 }
 
-void IgorEngine::PART_12_UPDATE_DIALOGUE_TOBIAS(int action) {
+void IgorEngine::PART_12_UPDATE_DIALOGUE_CHURCHMAN(int action) {
 	switch (action) {
 	case kUpdateDialogueAnimEndOfSentence:
 		PART_12_HELPER_8();
@@ -326,7 +327,7 @@
 
 void IgorEngine::PART_12_HANDLE_DIALOGUE_CHURCHMAN() {
 	loadDialogueData(DLG_OutsideChurch);
-	_updateDialogue = &IgorEngine::PART_12_UPDATE_DIALOGUE_TOBIAS;
+	_updateDialogue = &IgorEngine::PART_12_UPDATE_DIALOGUE_CHURCHMAN;
 	handleDialogue(95, 55, 51, 28, 63);
 	_updateDialogue = 0;
 }
@@ -403,7 +404,7 @@
 	ADD_DIALOGUE_TEXT(214, 1);
 	ADD_DIALOGUE_TEXT(215, 1);
 	SET_DIALOGUE_TEXT(1, 3);
-	_updateDialogue = &IgorEngine::PART_12_UPDATE_DIALOGUE_TOBIAS;
+	_updateDialogue = &IgorEngine::PART_12_UPDATE_DIALOGUE_CHURCHMAN;
 	startCutsceneDialogue(95, 55, 51, 28, 63);
 	waitForEndOfCutsceneDialogue(95, 55, 51, 28, 63);
 	_updateDialogue = 0;

Modified: scummvm/trunk/engines/igor/parts/part_13.cpp
===================================================================
--- scummvm/trunk/engines/igor/parts/part_13.cpp	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/parts/part_13.cpp	2007-11-18 06:25:23 UTC (rev 29552)
@@ -28,6 +28,7 @@
 namespace Igor {
 
 void IgorEngine::PART_13_EXEC_ACTION(int action) {
+	debugC(9, kDebugGame, "PART_13_EXEC_ACTION %d", action);
 	switch (action) {
 	case 101:
 		PART_13_ACTION_101_103();

Modified: scummvm/trunk/engines/igor/parts/part_14.cpp
===================================================================
--- scummvm/trunk/engines/igor/parts/part_14.cpp	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/parts/part_14.cpp	2007-11-18 06:25:23 UTC (rev 29552)
@@ -33,6 +33,7 @@
 static int VAR_CURRENT_CHURCH_MOSAIC_STONE;
 
 void IgorEngine::PART_14_EXEC_ACTION(int action) {
+	debugC(9, kDebugGame, "PART_14_EXEC_ACTION %d", action);
 	switch (action) {
 	case 101:
 		PART_14_ACTION_101();

Modified: scummvm/trunk/engines/igor/parts/part_16.cpp
===================================================================
--- scummvm/trunk/engines/igor/parts/part_16.cpp	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/parts/part_16.cpp	2007-11-18 06:25:23 UTC (rev 29552)
@@ -30,6 +30,7 @@
 static int VAR_CURRENT_TALKING_ACTOR;
 
 void IgorEngine::PART_16_EXEC_ACTION(int action) {
+	debugC(9, kDebugGame, "PART_16_EXEC_ACTION %d", action);
 	switch (action) {
 	case 101:
 		PART_16_ACTION_101();

Modified: scummvm/trunk/engines/igor/parts/part_17.cpp
===================================================================
--- scummvm/trunk/engines/igor/parts/part_17.cpp	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/parts/part_17.cpp	2007-11-18 06:25:23 UTC (rev 29552)
@@ -30,6 +30,7 @@
 static int VAR_CURRENT_TALKING_ACTOR;
 
 void IgorEngine::PART_17_EXEC_ACTION(int action) {
+	debugC(9, kDebugGame, "PART_17_EXEC_ACTION %d", action);
 	switch (action) {
 	case 101:
 		PART_17_ACTION_101();

Modified: scummvm/trunk/engines/igor/parts/part_95.cpp
===================================================================
--- scummvm/trunk/engines/igor/parts/part_95.cpp	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/parts/part_95.cpp	2007-11-18 06:25:23 UTC (rev 29552)
@@ -27,40 +27,142 @@
 
 namespace Igor {
 
+struct SharewareScreenString {
+	uint8 color;
+	int y;
+	const char *str;
+};
+
+static const SharewareScreenString STR_SHAREWARE[] = {
+	// 950
+	{ 255,  30, "\"Igor. Objective Uikokahonia\"" },
+	{ 228,  70, "This is SHAREWARE!" },
+	{ 228,  81, "You can copy this version!" },
+	{ 228,  96, "Pass it around, give it to your friends, family," },
+	{ 228, 107, "colleagues and upload it to your favorite BBS." },
+	{ 228, 122, "Let everyone enjoy IGOR!" },
+	{ 228, 161, "To place an order: 1-800-OPTIK-99" },
+	// 951
+	{ 255,  30, "\"Igor. Objective Uikokahonia\"" },
+	{ 228,  42, "Shareware version" },
+	{ 228,  85, "Order the full IGOR game for only $34.99 US." },
+	{ 228,  96, "$5.00 for shipping and handling (US & CANADA)." },
+	{ 228, 107, "Please add $3.00 for international shipping." },
+	{ 228, 161, "To place an order: 1-800-OPTIK-99" },
+	// 952
+	{ 255,  30, "\"Igor. Objective Uikokahonia\"" },
+	{ 228,  42, "Shareware version" },
+	{ 228,  70, "90 day limited warranty." },
+	{ 228,  85, "Please allow 2-4 days for delivery (US only)." },
+	{ 228,  96, "Elsewhere, up to a week or two..." },
+	{ 228, 111, "Overnight/second day shipping available an" },
+	{ 228, 122, "aditional change. Please call for exact pricing." },
+	{ 228, 161, "To place an order: 1-800-OPTIK-99" },
+	// 953
+	{ 255,  30, "\"Igor. Objective Uikokahonia\"" },
+	{ 228,  42, "Shareware version" },
+	{ 228,  70, "Three easy ways to order:" },
+	{ 228,  85, "- Call 1-800-678-4599 (orders only) and use" },
+	{ 228,  96, "Your Visa, Mastercard or Discover card." },
+	{ 228, 110, "- Fax your order (please include credit card" },
+	{ 228, 121, "information) to (412) 381-1031" },
+	{ 228, 161, "To place an order: 1-800-OPTIK-99" },
+	// 954
+	{ 255,  30, "\"Igor. Objective Uikokahonia\"" },
+	{ 228,  42, "Shareware version" },
+	{ 228,  74, "- Mail a check or money order to:" },
+	{ 228,  85, "Optik Software Inc." },
+	{ 228,  96, "1000 Napor Boulevard" },
+	{ 228, 107, "Pittsburgh, PA. 15205" },
+	{ 228, 118, "USA" },
+	{ 228, 161, "To place an order: 1-800-OPTIK-99" },
+	// 955
+	{ 255,  30, "\"Igor. Objective Uikokahonia\"" },
+	{ 240,  42, "Shareware version" },
+	{ 240,  79, "Optik Software Inc." },
+	{ 240,  90, "Orders only: 1-800-OPTIK-99 (67845-99)" },
+	{ 240, 101, "Fax: (412) 381-1031" },
+	{ 240, 112, "E-mail: optiksoft\xFA""aol.com" },
+	{ 240, 161, "To place an order: 1-800-OPTIK-99" },
+	// 956
+	{ 255,  30, "\"Igor. Objective Uikokahonia\"" },
+	{ 228,  42, "Shareware version" },
+	{ 228,  64, "A game by" },
+	{ 228,  80, "PENDULO STUDIOS" },
+	{ 228,  91, "P.O. Box 21091" },
+	{ 228, 102, "28009 Madrid" },
+	{ 228, 113, "Spain" },
+	{ 228, 128, "E-mail: 100641.1737\xFA""compuserve.com" },
+	{ 228, 161, "To place an order: 1-800-OPTIK-99" }
+};
+
 void IgorEngine::PART_95() {
 	memset(_currentPalette, 0, 768);
 	setPaletteRange(0, 255);
 	memset(_screenVGA, 0, 64000);
+	int startStr = -1, endStr = -1;
 	switch (_currentPart) {
 	case 950:
 		loadData(PAL_Shareware1, _paletteBuffer);
 		loadData(IMG_Shareware1, _screenVGA);
+		if (_gameVersion == kIdEngDemo110) {
+			startStr = 0;
+			endStr = 6;
+		}
 		break;
 	case 951:
 		loadData(PAL_Shareware2, _paletteBuffer);
 		loadData(IMG_Shareware2, _screenVGA);
+		if (_gameVersion == kIdEngDemo110) {
+			startStr = 7;
+			endStr = 12;
+		}
 		break;
 	case 952:
 		loadData(PAL_Shareware3, _paletteBuffer);
 		loadData(IMG_Shareware3, _screenVGA);
+		if (_gameVersion == kIdEngDemo110) {
+			startStr = 13;
+			endStr = 19;
+		}
 		break;
 	case 953:
 		loadData(PAL_Shareware4, _paletteBuffer);
 		loadData(IMG_Shareware4, _screenVGA);
+		if (_gameVersion == kIdEngDemo110) {
+			startStr = 20;
+			endStr = 27;
+		}
 		break;
 	case 954:
 		loadData(PAL_Shareware5, _paletteBuffer);
 		loadData(IMG_Shareware5, _screenVGA);
+		if (_gameVersion == kIdEngDemo110) {
+			startStr = 28;
+			endStr = 35;
+		}
 		break;
 	case 955:
 		loadData(PAL_Shareware6, _paletteBuffer);
 		loadData(IMG_Shareware6, _screenVGA);
+		if (_gameVersion == kIdEngDemo110) {
+			startStr = 36;
+			endStr = 42;
+		}
 		break;
 	case 956:
 		loadData(PAL_Shareware7, _paletteBuffer);
 		loadData(IMG_Shareware7, _screenVGA);
+		if (_gameVersion == kIdEngDemo110) {
+			startStr = 43;
+			endStr = 51;
+		}
 		break;
 	}
+	for (int i = startStr; i <= endStr; ++i) {
+		const SharewareScreenString *s = &STR_SHAREWARE[i];
+		drawString(_screenVGA, s->str, (320 - getStringWidth(s->str)) / 2, s->y, s->color, 0, 0);
+	}
 	fadeInPalette(768);
 	for (int i = 0; !_inputVars[kInputEscape] && i < 3000; ++i) {
 		waitForTimer();

Modified: scummvm/trunk/engines/igor/parts/part_main.cpp
===================================================================
--- scummvm/trunk/engines/igor/parts/part_main.cpp	2007-11-18 06:24:40 UTC (rev 29551)
+++ scummvm/trunk/engines/igor/parts/part_main.cpp	2007-11-18 06:25:23 UTC (rev 29552)
@@ -929,15 +929,6 @@
 		case 904:
 			PART_90();
 			break;
-		case 950:
-		case 951:
-		case 952:
-		case 953:
-		case 954:
-		case 955:
-		case 956:
-			PART_95();
-			break;
 		default:
 			warning("PART_MAIN() Unhandled part %d", _currentPart);
 			_currentPart = kInvalidPart;
@@ -974,7 +965,12 @@
 			}
 			_gameState.nextMusicCounter = 0;
 		}
-	} while (_currentPart != 255 && !_eventQuitGame);
+	} while (_currentPart != kInvalidPart && !_eventQuitGame);
+	if (_gameVersion == kIdEngDemo100 || _gameVersion == kIdEngDemo110) {
+		for (_currentPart = kSharewarePart; !_eventQuitGame && _currentPart <= kSharewarePart + 6; ++_currentPart) {
+			PART_95();
+		}
+	}
 }
 
 } // namespace Igor


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