[Scummvm-cvs-logs] SF.net SVN: scummvm: [21186] scummvm/trunk/engines/cine

cyx at users.sourceforge.net cyx at users.sourceforge.net
Thu Mar 9 14:38:03 CET 2006


Revision: 21186
Author:   cyx
Date:     2006-03-09 14:37:19 -0800 (Thu, 09 Mar 2006)
ViewCVS:  http://svn.sourceforge.net/scummvm/?rev=21186&view=rev

Log Message:
-----------
oo'ified sound code and added basic support for OS adlib music.

Modified Paths:
--------------
    scummvm/trunk/engines/cine/cine.cpp
    scummvm/trunk/engines/cine/main_loop.cpp
    scummvm/trunk/engines/cine/resource.cpp
    scummvm/trunk/engines/cine/resource.h
    scummvm/trunk/engines/cine/script.cpp
    scummvm/trunk/engines/cine/sfx_player.cpp
    scummvm/trunk/engines/cine/sfx_player.h
    scummvm/trunk/engines/cine/sound_driver.cpp
    scummvm/trunk/engines/cine/sound_driver.h
    scummvm/trunk/engines/cine/various.cpp
Modified: scummvm/trunk/engines/cine/cine.cpp
===================================================================
--- scummvm/trunk/engines/cine/cine.cpp	2006-03-09 20:50:19 UTC (rev 21185)
+++ scummvm/trunk/engines/cine/cine.cpp	2006-03-09 22:37:19 UTC (rev 21186)
@@ -46,8 +46,8 @@
 
 namespace Cine {
 
-Audio::Mixer * cine_g_mixer;
-AdlibMusic *g_cine_adlib;
+SoundDriver *g_soundDriver;
+SfxPlayer *g_sfxPlayer;
 
 static void initialize();
 
@@ -131,7 +131,6 @@
 		warning("Sound initialization failed.");
 	}
 
-	cine_g_mixer = _mixer;
 	_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
 	_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
 
@@ -163,7 +162,12 @@
 	_system->initSize(320, 200);
 	_system->endGFXTransaction();
 
-	g_cine_adlib = new AdlibMusic(_mixer);
+	if (gameType == GID_FW) {
+		g_soundDriver = new AdlibSoundDriverINS(_mixer);
+	} else {
+		g_soundDriver = new AdlibSoundDriverADL(_mixer);
+	}
+	g_sfxPlayer = new SfxPlayer(g_soundDriver);
 
 	initialize();
 
@@ -178,8 +182,8 @@
 	if (gameType == Cine::GID_FW)
 		snd_clearBasesonEntries();
 
-	delete g_cine_adlib;
-
+	delete g_soundDriver;
+	delete g_sfxPlayer;
 	return 0;
 }
 
@@ -196,7 +200,8 @@
 	partBuffer = (PartBuffer *)malloc(255 * sizeof(PartBuffer));
 
 	loadTextData("texte.dat", textDataPtr);
-	snd_loadBasesonEntries("BASESON.SND");
+	if (gameType == Cine::GID_FW)
+		snd_loadBasesonEntries("BASESON.SND");
 
 	for (i = 0; i < NUM_MAX_OBJECT; i++) {
 		objectTable[i].part = 0;

Modified: scummvm/trunk/engines/cine/main_loop.cpp
===================================================================
--- scummvm/trunk/engines/cine/main_loop.cpp	2006-03-09 20:50:19 UTC (rev 21185)
+++ scummvm/trunk/engines/cine/main_loop.cpp	2006-03-09 22:37:19 UTC (rev 21186)
@@ -28,6 +28,7 @@
 
 #include "cine/main_loop.h"
 #include "cine/object.h"
+#include "cine/sfx_player.h"
 #include "cine/various.h"
 
 namespace Cine {
@@ -142,17 +143,15 @@
 	strcpy(currentCtName, "");
 	strcpy(currentPartName, "");
 
-	stopSample();
+	g_sfxPlayer->stop();
 
 	do {
 		mainLoopSub3();
 		di = executePlayerInput();
 
-		if (var18 != 0) {
-			if (var18 >= 100 || var19) {
-				stopSample();
-			}
-		}
+//		if (g_sfxPlayer->_fadeOutCounter != 0 && g_sfxPlayer->_fadeOutCounter < 100) {
+//			g_sfxPlayer->stop();
+//		}
 
 		processSeqList();
 		executeList1();
@@ -232,7 +231,7 @@
 	} while (!exitEngine && !quitFlag && var21 != 7);
 
 	hideMouse();
-	stopSample();
+	g_sfxPlayer->stop();
 	closeEngine3();
 	unloadAllMasks();
 	freePrcLinkedList();

Modified: scummvm/trunk/engines/cine/resource.cpp
===================================================================
--- scummvm/trunk/engines/cine/resource.cpp	2006-03-09 20:50:19 UTC (rev 21185)
+++ scummvm/trunk/engines/cine/resource.cpp	2006-03-09 22:37:19 UTC (rev 21186)
@@ -22,11 +22,105 @@
  *
  */
 
+#include "common/file.h"
+
+#include "cine/cine.h"
 #include "cine/resource.h"
+#include "cine/unpack.h"
+#include "cine/various.h"
 
 namespace Cine {
 
 void checkDataDisk(int16 param) {
 }
 
+/* FW specific */
+static Common::File *snd_baseSndFile = NULL;
+static uint16 snd_numBasesonEntries = 0;
+static BasesonEntry *snd_basesonEntries = NULL;
+
+int snd_loadBasesonEntries(const char *fileName) {
+	int i;
+
+	snd_baseSndFile = new Common::File();
+	snd_baseSndFile->open(fileName);
+	if (!snd_baseSndFile->isOpen())
+		return -1;
+
+	snd_numBasesonEntries = snd_baseSndFile->readUint16BE();
+	snd_baseSndFile->readUint16BE();	/* entry_size */
+	snd_basesonEntries = (BasesonEntry *)malloc(snd_numBasesonEntries * sizeof(BasesonEntry));
+	if (snd_basesonEntries) {
+		for (i = 0; i < snd_numBasesonEntries; ++i) {
+			BasesonEntry *be = &snd_basesonEntries[i];
+			snd_baseSndFile->read(be->name, 14);
+			be->offset = snd_baseSndFile->readUint32BE();
+			be->size = snd_baseSndFile->readUint32BE();
+			be->unpackedSize = snd_baseSndFile->readUint32BE();
+			snd_baseSndFile->readUint32BE();	/* unused */
+		}
+	}
+	return 0;
+}
+
+void snd_clearBasesonEntries() {
+	snd_baseSndFile->close();
+	delete snd_baseSndFile;
+	free(snd_basesonEntries);
+	snd_basesonEntries = NULL;
+	snd_numBasesonEntries = 0;
+}
+
+static int snd_findBasesonEntry(const char *entryName) {
+	int i;
+	char *p;
+	char basesonEntryName[20];
+
+	assert(strlen(entryName) < 20);
+	strcpy(basesonEntryName, entryName);
+	for (p = basesonEntryName; *p; ++p) {
+		if (*p >= 'a' && *p <= 'z')
+			*p += 'A' - 'a';
+	}
+
+	for (i = 0; i < snd_numBasesonEntries; ++i) {
+		if (strcmp(snd_basesonEntries[i].name, basesonEntryName) == 0)
+			return i;
+	}
+	return -1;
+}
+
+uint8 *snd_loadBasesonEntry(const char *entryName) {
+	int entryNum;
+	uint8 *entryData = NULL;
+
+	if (gameType == Cine::GID_OS) {
+		entryNum = findFileInBundle((const char *)entryName);
+		if (entryNum != -1)
+			entryData = readBundleFile(entryNum);
+	} else {
+		entryNum = snd_findBasesonEntry(entryName);
+		if (entryNum != -1 && entryNum < snd_numBasesonEntries) {
+			const BasesonEntry *be = &snd_basesonEntries[entryNum];
+			entryData = (uint8 *)malloc(be->unpackedSize);
+			if (entryData) {
+				if (be->unpackedSize > be->size) {
+					uint8 *tempData = (uint8 *)malloc(be->size);
+					if (tempData) {
+						snd_baseSndFile->seek(be->offset, SEEK_SET);
+						snd_baseSndFile->read(tempData, be->size);
+						delphineUnpack(entryData, tempData, be->size);
+						free(tempData);
+					}
+				} else {
+					snd_baseSndFile->seek(be->offset, SEEK_SET);
+					snd_baseSndFile->read(entryData, be->size);
+				}
+			}
+		}
+	}
+
+	return entryData;
+}
+
 } // End of namespace Cine

Modified: scummvm/trunk/engines/cine/resource.h
===================================================================
--- scummvm/trunk/engines/cine/resource.h	2006-03-09 20:50:19 UTC (rev 21185)
+++ scummvm/trunk/engines/cine/resource.h	2006-03-09 22:37:19 UTC (rev 21186)
@@ -30,7 +30,17 @@
 
 namespace Cine {
 
+struct BasesonEntry {
+	char name[14];
+	uint32 offset;
+	uint32 size;
+	uint32 unpackedSize;
+};
+
 void checkDataDisk(int16 param);
+extern int snd_loadBasesonEntries(const char *fileName);
+extern void snd_clearBasesonEntries();
+extern uint8 *snd_loadBasesonEntry(const char *entryName);
 
 } // End of namespace Cine
 

Modified: scummvm/trunk/engines/cine/script.cpp
===================================================================
--- scummvm/trunk/engines/cine/script.cpp	2006-03-09 20:50:19 UTC (rev 21185)
+++ scummvm/trunk/engines/cine/script.cpp	2006-03-09 22:37:19 UTC (rev 21186)
@@ -1784,27 +1784,26 @@
 		case 0x6D:
 			{
 				DEBUG_SCRIPT(currentLine, "loadMusic(%s)", currentScriptPtr + currentPosition);
-				snd_loadSong((char *)(currentScriptPtr + currentPosition));
-
-				currentPosition += strlen((char *)(currentScriptPtr + currentPosition)) + 1;
+				g_sfxPlayer->load((const char *)(currentScriptPtr + currentPosition));
+				currentPosition += strlen((const char *)(currentScriptPtr + currentPosition)) + 1;
 				break;
 			}
 		case 0x6E:
 			{
 				DEBUG_SCRIPT(currentLine, "playMusic()");
-				snd_playSong();
+				g_sfxPlayer->play();
 				break;
 			}
 		case 0x6F:
 			{
 				DEBUG_SCRIPT(currentLine, "fadeOutMusic()");
-				snd_fadeOutSong();
+				g_sfxPlayer->fadeOut();
 				break;
 			}
 		case 0x70:
 			{
 				DEBUG_SCRIPT(currentLine, "stopSample()");
-				snd_stopSong();
+				g_sfxPlayer->stop();
 				break;
 			}
 		case 0x77:
@@ -1840,16 +1839,20 @@
 					volume = 63;
 
 				if (animDataTable[anim].ptr1) {
-					if (channel >= 10)
+					if (channel >= 10) {
 						channel -= 10;
-					if (volume < 50)
+					}
+					if (volume < 50) {
 						volume = 50;
-					if (snd_songIsPlaying)
-						snd_stopSong();
-					if (flag == 0xFFFF)
-						(*snd_driver.playSound)(animDataTable[anim].ptr1, channel, volume);
-					else
-						snd_resetChannel(channel);
+					}
+						
+					g_sfxPlayer->stop();
+					
+					if (flag == 0xFFFF) {
+						g_soundDriver->playSound(animDataTable[anim].ptr1, channel, volume);
+					} else {
+						g_soundDriver->resetChannel(channel);
+					}
 				}
 				break;
 			}

Modified: scummvm/trunk/engines/cine/sfx_player.cpp
===================================================================
--- scummvm/trunk/engines/cine/sfx_player.cpp	2006-03-09 20:50:19 UTC (rev 21185)
+++ scummvm/trunk/engines/cine/sfx_player.cpp	2006-03-09 22:37:19 UTC (rev 21186)
@@ -24,7 +24,6 @@
 
 #include "common/stdafx.h"
 #include "common/system.h"
-#include "common/file.h"
 
 #include "cine/cine.h"
 #include "cine/sfx_player.h"
@@ -34,242 +33,161 @@
 
 namespace Cine {
 
-uint16 snd_eventsDelay;
-int snd_songIsPlaying = 0;
-uint8 snd_nullInstrument[] = { 0, 0 };
-SfxState snd_sfxState;
+SfxPlayer::SfxPlayer(SoundDriver *driver)
+	: _playing(false), _driver(driver) {
+	memset(_instrumentsData, 0, sizeof(_instrumentsData));
+	_sfxData = NULL;
+	_fadeOutCounter = 0;
+	_driver->setUpdateCallback(updateCallback, this);
+}
 
-static uint8 snd_mute = 0;
-static char snd_songFileName[30];
-
-/* LVDT specific */
-static Common::File *snd_baseSndFile = NULL;
-static uint16 snd_numBasesonEntries = 0;
-static BasesonEntry *snd_basesonEntries = NULL;
-
-int snd_loadBasesonEntries(const char *fileName) {
-	int i;
-
-	snd_baseSndFile = new Common::File();
-	snd_baseSndFile->open(fileName);
-	if (!snd_baseSndFile->isOpen())
-		return -1;
-
-	snd_numBasesonEntries = snd_baseSndFile->readUint16BE();
-	snd_baseSndFile->readUint16BE();	/* entry_size */
-	snd_basesonEntries = (BasesonEntry *)malloc(snd_numBasesonEntries * sizeof(BasesonEntry));
-	if (snd_basesonEntries) {
-		for (i = 0; i < snd_numBasesonEntries; ++i) {
-			BasesonEntry *be = &snd_basesonEntries[i];
-			snd_baseSndFile->read(be->name, 14);
-			be->offset = snd_baseSndFile->readUint32BE();
-			be->size = snd_baseSndFile->readUint32BE();
-			be->unpackedSize = snd_baseSndFile->readUint32BE();
-			snd_baseSndFile->readUint32BE();	/* unused */
-		}
+SfxPlayer::~SfxPlayer() {
+	_driver->setUpdateCallback(NULL, NULL);
+	if (_playing) {
+		stop();
 	}
-	return 0;
 }
 
-void snd_clearBasesonEntries() {
-	snd_baseSndFile->close();
-	delete snd_baseSndFile;
-	free(snd_basesonEntries);
-	snd_basesonEntries = NULL;
-	snd_numBasesonEntries = 0;
-}
+bool SfxPlayer::load(const char *song) {
+	debug(9, "SfxPlayer::load('%s')", song);
+	
+	/* stop (w/ fade out) the previous song */
+	while (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
+		g_system->delayMillis(50);
+	}
+	_fadeOutCounter = 0;
 
-static int snd_findBasesonEntry(const char *entryName) {
-	int i;
-	char *p;
-	char basesonEntryName[20];
-
-	assert(strlen(entryName) < 20);
-	strcpy(basesonEntryName, entryName);
-	for (p = basesonEntryName; *p; ++p) {
-		if (*p >= 'a' && *p <= 'z')
-			*p += 'A' - 'a';
+	if (_playing) {
+		stop();
 	}
 
-	for (i = 0; i < snd_numBasesonEntries; ++i) {
-		if (strcmp(snd_basesonEntries[i].name, basesonEntryName) == 0)
-			return i;
+	/* like the original PC version, skip introduction song (file doesn't exist) */
+	if (gameType == Cine::GID_OS && strncmp(song, "INTRO", 5) == 0) {
+		return 0;
 	}
-	return -1;
-}
+		
+	_sfxData = snd_loadBasesonEntry(song);
+	if (!_sfxData) {
+		warning("Unable to load soundfx module '%s'", song);
+		return 0;
+	}
 
-static uint8 *snd_loadBasesonEntry(const char *entryName) {
-	int entryNum;
-	uint8 *entryData = NULL;
-
-	if (gameType == Cine::GID_OS) {
-		entryNum = findFileInBundle((const char *)entryName);
-		if (entryNum != -1)
-			entryData = readBundleFile(entryNum);
-	} else {
-		entryNum = snd_findBasesonEntry(entryName);
-		if (entryNum != -1 && entryNum < snd_numBasesonEntries) {
-			const BasesonEntry *be = &snd_basesonEntries[entryNum];
-			entryData = (uint8 *)malloc(be->unpackedSize);
-			if (entryData) {
-				if (be->unpackedSize > be->size) {
-					uint8 *tempData = (uint8 *)malloc(be->size);
-					if (tempData) {
-						snd_baseSndFile->seek(be->offset, SEEK_SET);
-						snd_baseSndFile->read(tempData, be->size);
-						delphineUnpack(entryData, tempData, be->size);
-						free(tempData);
-					}
-				} else {
-					snd_baseSndFile->seek(be->offset, SEEK_SET);
-					snd_baseSndFile->read(entryData, be->size);
-				}
+	for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
+		_instrumentsData[i] = NULL;
+		
+		char instrument[13];
+		memcpy(instrument, _sfxData + 20 + i * 30, 12);
+		instrument[12] = '\0';
+		
+		if (strlen(instrument) != 0) {
+			char *dot = strrchr(instrument, '.');
+			if (dot) {
+				*dot = '\0';
 			}
+			strcat(instrument, _driver->getInstrumentExtension());
+			_instrumentsData[i] = snd_loadBasesonEntry(instrument);
+			if (!_instrumentsData[i]) {
+				warning("Unable to load soundfx instrument '%s'", instrument);
+			}
 		}
 	}
-
-	return entryData;
+	return 1;
 }
 
-void snd_stopSong() {
-	int i;
-
-	snd_songFileName[0] = '\0';
-	snd_songIsPlaying = 0;
-	snd_fadeOutCounter = 0;
-
-	for (i = 0; i < 4; ++i)
-		(*snd_driver.stopChannel) (i);
-
-	snd_adlibDriverStopSong();
-	snd_freeSong();
+void SfxPlayer::play() {
+	debug(9, "SfxPlayer::play()");
+	if (_sfxData) {
+		for (int i = 0; i < NUM_CHANNELS; ++i) {
+			_instrumentsChannelTable[i] = -1;
+		}
+		_currentPos = 0;
+		_currentOrder = 0;
+		_numOrders = _sfxData[470];
+		_eventsDelay = (252 - _sfxData[471]) * 50 / 1060;
+		_updateTicksCounter = 0;
+		_playing = true;
+	}
 }
 
-void snd_freeSong() {
-	int i;
-
-	for (i = 0; i < 15; ++i) {
-		if (snd_sfxState.instruments[i] != snd_nullInstrument)
-			free(snd_sfxState.instruments[i]);
+void SfxPlayer::stop() {
+	_fadeOutCounter = 0;
+	_playing = false;
+	for (int i = 0; i < NUM_CHANNELS; ++i) {
+		_driver->stopChannel(i);
 	}
-	free(snd_sfxState.songData);
-	memset(&snd_sfxState, 0, sizeof(snd_sfxState));
+	_driver->stopSound();
+	unload();
 }
 
-int snd_loadSong(const char *songName) {
-	int i;
-
-	while (snd_fadeOutCounter != 0 && snd_fadeOutCounter < 100)
-		g_system->delayMillis(40);
-
-	snd_fadeOutCounter = 0;
-
-	if (snd_songIsPlaying)
-		snd_stopSong();
-
-	if ((gameType == Cine::GID_OS) && (strncmp(songName, "INTRO", 5) == 0))
-		return 0;
-
-	strcpy(snd_songFileName, songName);
-	if (gameType == Cine::GID_OS)
-		strcat(snd_songFileName, ".IST");
-
-	snd_sfxState.songData = snd_loadBasesonEntry(songName);
-	if (!snd_sfxState.songData)
-		return 0;
-
-	for (i = 0; i < 15; ++i) {
-		char instrumentName[13];
-		memcpy(instrumentName, snd_sfxState.songData + 20 + i * 30, 12);
-		instrumentName[12] = '\0';
-
-		snd_sfxState.instruments[i] = snd_nullInstrument;
-		if (strlen(instrumentName) != 0) {
-			char *dot = strrchr(instrumentName, '.');
-			if (dot)
-				*dot = '\0';
-
-			if (gameType == Cine::GID_OS)
-				strcat(instrumentName, ".ADL");
-			else
-				strcat(instrumentName, ".INS");
-
-			snd_sfxState.instruments[i] =
-			    snd_loadBasesonEntry(instrumentName);
-		}
+void SfxPlayer::fadeOut() {
+	if (_playing) {
+		_fadeOutCounter = 1;
+		_playing = false;
 	}
-	return 1;
 }
 
-void snd_fadeOutSong() {
-	if (snd_songIsPlaying) {
-		snd_songFileName[0] = '\0';
-		snd_songIsPlaying = 0;
-		snd_fadeOutCounter = 1;
-	}
+void SfxPlayer::updateCallback(void *ref) {
+	((SfxPlayer *)ref)->update();
 }
 
-void snd_playSong() {
-	if (strlen(snd_songFileName) != 0) {
-		snd_sfxState.currentInstrumentChannel[0] = -1;
-		snd_sfxState.currentInstrumentChannel[1] = -1;
-		snd_sfxState.currentInstrumentChannel[2] = -1;
-		snd_sfxState.currentInstrumentChannel[3] = -1;
-		snd_sfxState.currentOrder = 0;
-		snd_sfxState.currentPos = 0;
-		snd_sfxState.numOrders = snd_sfxState.songData[470];
-		snd_eventsDelay = (252 - snd_sfxState.songData[471]) * 25 * 2 / 1060;
-		snd_songTicksCounter = 0;
-		snd_songIsPlaying = 1;
+void SfxPlayer::update() {
+	if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) {
+		++_updateTicksCounter;
+		if (_updateTicksCounter > _eventsDelay) {
+			handleEvents();
+			_updateTicksCounter = 0;
+		}
 	}
 }
 
-void snd_handleEvents() {
-	int i;
-	const uint8 *patternData = snd_sfxState.songData + 600;
-	const uint8 *orderTable = snd_sfxState.songData + 472;
-	uint16 patternNum = orderTable[snd_sfxState.currentOrder] * 1024;
+void SfxPlayer::handleEvents() {
+	const uint8 *patternData = _sfxData + 600;
+	const uint8 *orderTable = _sfxData + 472;
+	uint16 patternNum = orderTable[_currentOrder] * 1024;
 
-	for (i = 0; i < 4; ++i) {
-		snd_handlePattern(i, patternData + patternNum + snd_sfxState.currentPos);
+	for (int i = 0; i < 4; ++i) {
+		handlePattern(i, patternData + patternNum + _currentPos);
 		patternData += 4;
 	}
 
-	if (snd_fadeOutCounter != 0 && snd_fadeOutCounter < 100)
-		snd_fadeOutCounter += 4;
-
-	snd_sfxState.currentPos += 16;
-	if (snd_sfxState.currentPos >= 1024) {
-		snd_sfxState.currentPos = 0;
-		++snd_sfxState.currentOrder;
-		if (snd_sfxState.currentOrder == snd_sfxState.numOrders)
-			snd_sfxState.currentOrder = 0;
+	if (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
+		_fadeOutCounter += 2;
 	}
+	_currentPos += 16;
+	if (_currentPos >= 1024) {
+		_currentPos = 0;
+		++_currentOrder;
+		if (_currentOrder == _numOrders) {
+			_currentOrder = 0;
+		}
+	}
+	debug(7, "_currentOrder=%d/%d _currentPos=%d", _currentOrder, _numOrders, _currentPos);
 }
 
-void snd_handlePattern(int channelNum, const uint8 *patternData) {
-	uint16 instrNum = patternData[2] >> 4;
-	snd_adlibInstrumentsTable[channelNum] = snd_nullInstrument;
-	if (instrNum != 0) {
-		if (snd_sfxState.currentInstrumentChannel[channelNum] != instrNum) {
-			snd_sfxState.currentInstrumentChannel[channelNum] = instrNum;
-			(*snd_driver.setupChannel) (channelNum, snd_sfxState.instruments[instrNum - 1], instrNum - 1);
-		} else if (snd_fadeOutCounter != 0) {
-			instrNum = snd_sfxState.currentInstrumentChannel[channelNum];
-			if (instrNum != 0)
-				(*snd_driver.setupChannel)(channelNum, snd_sfxState.instruments[instrNum - 1], instrNum - 1);
+void SfxPlayer::handlePattern(int channel, const uint8 *patternData) {
+	int instrument = patternData[2] >> 4;
+	if (instrument != 0) {
+		--instrument;
+		if (_instrumentsChannelTable[channel] != instrument || _fadeOutCounter != 0) {
+			_instrumentsChannelTable[channel] = instrument;
+			const int volume = _sfxData[instrument] - _fadeOutCounter;
+			_driver->setupChannel(channel, _instrumentsData[instrument], instrument, volume);
 		}
-		snd_adlibInstrumentsTable[channelNum] = snd_sfxState.instruments[instrNum - 1];
 	}
-	if (snd_mute != 0)
-		(*snd_driver.stopChannel)(channelNum);
-	else {
-		int16 freq = (int16)READ_BE_UINT16(patternData);
-		if (freq > 0) {
-			(*snd_driver.stopChannel)(channelNum);
-			(*snd_driver.setChannelFrequency)(channelNum, freq);
-		}
+	int16 freq = (int16)READ_BE_UINT16(patternData);
+	if (freq > 0) {
+		_driver->stopChannel(channel);
+		_driver->setChannelFrequency(channel, freq);
 	}
 }
 
+void SfxPlayer::unload() {
+	for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
+		free(_instrumentsData[i]);
+		_instrumentsData[i] = NULL;
+	}
+	free(_sfxData);
+	_sfxData = NULL;
+}
+
 } // End of namespace Cine

Modified: scummvm/trunk/engines/cine/sfx_player.h
===================================================================
--- scummvm/trunk/engines/cine/sfx_player.h	2006-03-09 20:50:19 UTC (rev 21185)
+++ scummvm/trunk/engines/cine/sfx_player.h	2006-03-09 22:37:19 UTC (rev 21186)
@@ -27,37 +27,48 @@
 
 namespace Cine {
 
-struct BasesonEntry {
-	char name[14];
-	uint32 offset;
-	uint32 size;
-	uint32 unpackedSize;
-};
+class SoundDriver;
 
-struct SfxState {
-	uint8 *songData;
-	int currentInstrumentChannel[4];
-	uint8 *instruments[15];
-	int currentOrder;
-	int currentPos;
-	int numOrders;
+class SfxPlayer {
+public:
+
+	enum {
+		NUM_INSTRUMENTS = 15,
+		NUM_CHANNELS = 4
+	};
+	
+	SfxPlayer(SoundDriver *driver);
+	~SfxPlayer();
+
+	bool load(const char *song);
+	void play();
+	void stop();
+	void fadeOut();
+
+	static void updateCallback(void *ref);
+
+private:
+
+	void update();
+	void handleEvents();
+	void handlePattern(int channel, const uint8 *patternData);
+	void unload();
+
+	bool _playing;
+	int _currentPos;
+	int _currentOrder;
+	int _numOrders;
+	int _eventsDelay;
+	int _fadeOutCounter;
+	int _updateTicksCounter;
+	int _instrumentsChannelTable[NUM_CHANNELS];
+	uint8 *_sfxData;
+	uint8 *_instrumentsData[NUM_INSTRUMENTS];
+	SoundDriver *_driver;
 };
 
-extern uint16 snd_eventsDelay;
-extern int snd_songIsPlaying;
-extern uint8 snd_nullInstrument[];
-extern SfxState snd_sfxState;
+extern SfxPlayer *g_sfxPlayer; // TEMP
 
-extern int snd_loadBasesonEntries(const char *fileName);
-extern void snd_clearBasesonEntries();
-extern void snd_stopSong();
-extern void snd_freeSong();
-extern int snd_loadSong(const char *songName);
-extern void snd_fadeOutSong();
-extern void snd_playSong();
-extern void snd_handleEvents();
-extern void snd_handlePattern(int channelNum, const uint8 *patternData);
-
 } // End of namespace Cine
 
 #endif				/* _SFXPLAYER_H_ */

Modified: scummvm/trunk/engines/cine/sound_driver.cpp
===================================================================
--- scummvm/trunk/engines/cine/sound_driver.cpp	2006-03-09 20:50:19 UTC (rev 21185)
+++ scummvm/trunk/engines/cine/sound_driver.cpp	2006-03-09 22:37:19 UTC (rev 21186)
@@ -23,383 +23,412 @@
  */
 
 #include "cine/cine.h"
-#include "cine/sfx_player.h"
 #include "cine/sound_driver.h"
 
 #include "sound/mixer.h"
-#include "sound/fmopl.h"
 
 namespace Cine {
 
-extern AdlibMusic *g_cine_adlib;
+void SoundDriver::setUpdateCallback(UpdateCallback upCb, void *ref) {
+	_upCb = upCb;
+	_upRef = ref;
+}
 
-uint8 snd_useAdlib = 0;
-uint16 snd_fadeOutCounter = 0;
-uint16 snd_songTicksCounter = 0;
-uint8 *snd_adlibInstrumentsTable[4];
-SoundDriver snd_driver;
+void SoundDriver::findNote(int freq, int *note, int *oct) const {
+	*note = _noteTableCount - 1;
+	for (int i = 0; i < _noteTableCount; ++i) {
+		if (_noteTable[i] <= freq) {
+			*note = i;
+			break;
+		}
+	}
+	*oct = *note / 12;
+}
 
-static uint8 snd_adlibVibrato = 0;
-static int16 snd_adlibChannelVolume[4];
+void SoundDriver::resetChannel(int channel) {
+	stopChannel(channel);
+	stopSound();
+}
 
-static const uint16 snd_adlibFreqTable[] = {
-	0x0157, 0x016C, 0x0181, 0x0198, 0x01B1, 0x01CB, 0x01E6, 0x0203,
-	0x0222, 0x0243, 0x0266, 0x028A
-};
+AdlibSoundDriver::AdlibSoundDriver(Audio::Mixer *mixer)
+	: _mixer(mixer) {
+	_sampleRate = _mixer->getOutputRate();
+	_opl = makeAdlibOPL(_sampleRate);
+	memset(_channelsVolumeTable, 0, sizeof(_channelsVolumeTable));
+	memset(_instrumentsTable, 0, sizeof(_instrumentsTable));
+	initCard();
+	_mixer->setupPremix(this);
+}
 
-static const uint8 snd_adlibOpTable[] = {
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x08, 0x09, 0x0A,
-	0x0B, 0x0C, 0x0D, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15
-};
-
-static const uint8 snd_adlibNoteTable[] = {
-	0x00, 0x03, 0x01, 0x04, 0x02, 0x05, 0x06, 0x09, 0x07,
-	0x0A, 0x08, 0x0B, 0x0C, 0x0F, 0x10, 0x10, 0x0E, 0x0E,
-	0x11, 0x11, 0x0D, 0x0D, 0x00, 0x00
-};
-
-static const int16 snd_adlibNoteFreqTable[] = {
-	0x0EEE, 0x0E17, 0x0D4D, 0x0C8C, 0x0BD9, 0x0B2F, 0x0A8E, 0x09F7,
-	0x0967, 0x08E0, 0x0861, 0x07E8, 0x0777, 0x070B, 0x06A6, 0x0647,
-	0x05EC, 0x0597, 0x0547, 0x04FB, 0x04B3, 0x0470, 0x0430, 0x03F4,
-	0x03BB, 0x0385, 0x0353, 0x0323, 0x02F6, 0x02CB, 0x02A3, 0x027D,
-	0x0259, 0x0238, 0x0218, 0x01FA, 0x01DD, 0x01C2, 0x01A9, 0x0191,
-	0x017B, 0x0165, 0x0151, 0x013E, 0x012C, 0x011C, 0x010C, 0x00FD,
-	0x00EE, 0x00E1, 0x00D4, 0x00C8, 0x00BD, 0x00B2, 0x00A8, 0x009F,
-	0x0096, 0x008E, 0x0086, 0x007E, 0x0077, 0x0070, 0x006A, 0x0064,
-	0x005E, 0x0059, 0x0054, 0x004F, 0x004B, 0x0047, 0x0043, 0x003F,
-	0x003B, 0x0038, 0x0035, 0x0032, 0x002F, 0x002C, 0x002A, 0x0027,
-	0x0025, 0x0023, 0x0021, 0x001F, 0x001D, 0x001C, 0x001A, 0x0019,
-	0x0017, 0x0016, 0x0015, 0x0013, 0x0012, 0x0011, 0x0010, 0x000F
-};
-
-static void snd_adlibWriteData(int port, int value) {
-	OPLWriteReg(g_cine_adlib->getOPL(), port, value);
+AdlibSoundDriver::~AdlibSoundDriver() {
+	_mixer->setupPremix(NULL);
 }
 
-static void snd_adlibDriverSetupInstrument(const uint8 *instrumentData, int channelNum) {
-	int16 tmp;
-
-	uint8 waveSelect1 = instrumentData[54] & 3;	/* var2 */
-	uint8 waveSelect2 = instrumentData[56] & 3;	/* var1 */
-
-	uint8 fl = *instrumentData++;	/* varB */
-	uint8 ch = *instrumentData++;	/* var4 */
-
-	uint8 adlibOp1, adlibOp2;	/* _di, varA */
-
-	if (fl != 0) {
-		adlibOp1 = snd_adlibOpTable[snd_adlibNoteTable[ch * 2 + 0]];
-		adlibOp2 = snd_adlibOpTable[snd_adlibNoteTable[ch * 2 + 1]];
-	} else {
-		adlibOp1 = snd_adlibOpTable[snd_adlibNoteTable[channelNum * 2 + 0]];
-		adlibOp2 = snd_adlibOpTable[snd_adlibNoteTable[channelNum * 2 + 1]];
+void AdlibSoundDriver::setupChannel(int channel, const uint8 *data, int instrument, int volume) {
+	assert(channel < 4);
+	if (data) {
+		if (volume > 80) {
+			volume = 80;
+		} else if (volume < 0) {
+			volume = 0;
+		}
+		volume += volume / 4;
+		if (volume > 127) {
+			volume = 127;
+		}
+		_channelsVolumeTable[channel] = volume;
+		setupInstrument(data, channel);
 	}
+}
 
-	if (fl == 0 || ch == 6) {
-		// vibrato
-		tmp = 0;
-		if (READ_LE_UINT16(instrumentData + 18) != 0)
-			tmp |= 0x80;
-		if (READ_LE_UINT16(instrumentData + 20) != 0)
-			tmp |= 0x40;
-		if (READ_LE_UINT16(instrumentData + 10) != 0)
-			tmp |= 0x20;
-		if (READ_LE_UINT16(instrumentData + 22) != 0)
-			tmp |= 0x10;
-		tmp |= (READ_LE_UINT16(instrumentData + 2) & 0xF);
-		snd_adlibWriteData(ADLIB_REG_AM_VIBRATO_EG_KS + adlibOp1, tmp);
-
-		// key scaling
-		tmp = 0x3F - (READ_LE_UINT16(instrumentData + 16) & 0x3F);
-		tmp = snd_adlibChannelVolume[channelNum] * tmp;
-		tmp += tmp + 0x7F;
-		tmp = 0x3F - (tmp / 0xFE);
-		if (READ_LE_UINT16(instrumentData + 24) != 0)
-			tmp = READ_LE_UINT16(instrumentData + 16) & 0x3F;
-		tmp |= READ_LE_UINT16(instrumentData) << 6;
-		snd_adlibWriteData(ADLIB_REG_KEY_SCALING_OPERATOR_OUTPUT + adlibOp1, tmp);
-
-		// attack/decay rates
-		tmp = (READ_LE_UINT16(instrumentData + 6) << 4) | (READ_LE_UINT16(instrumentData + 12) & 0xF);
-		snd_adlibWriteData(ADLIB_REG_ATTACK_RATE_DECAY_RATE + adlibOp1, tmp);
-
-		// sustain/release rates
-		tmp = (READ_LE_UINT16(instrumentData + 8) << 4) | (READ_LE_UINT16(instrumentData + 14) & 0xF);
-		snd_adlibWriteData(ADLIB_REG_SUSTAIN_LEVEL_RELEASE_RATE_0 + adlibOp1, tmp);
-
-		if (fl != 0) {
-			tmp = READ_LE_UINT16(instrumentData + 4) * 2;
-			if (READ_LE_UINT16(instrumentData + 24) == 0)
-				tmp |= 1;
-
-			snd_adlibWriteData(ADLIB_REG_FEEDBACK_STRENGTH_CONNECTION_TYPE + ch, tmp);
-		} else {
-			tmp = READ_LE_UINT16(instrumentData + 4) * 2;
-			if (READ_LE_UINT16(instrumentData + 24) == 0)
-				tmp |= 1;
-
-			snd_adlibWriteData(ADLIB_REG_FEEDBACK_STRENGTH_CONNECTION_TYPE + channelNum, tmp);
+void AdlibSoundDriver::stopChannel(int channel) {
+	assert(channel < 4);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	if (ins) {
+		if (ins->mode != 0 && ins->channel == 6) {
+			channel = 6;
 		}
-		snd_adlibWriteData(ADLIB_REG_WAVE_SELECT + adlibOp1, waveSelect1);
-		instrumentData += 26;
+		if (ins->mode == 0 || ins->channel == 6) {
+			OPLWriteReg(_opl, 0xB0 | channel, 0);
+		}
+		if (ins->mode != 0) {
+			_vibrato &= (1 << (10 - ins->channel)) ^ 0xFF;
+			OPLWriteReg(_opl, 0xBD, _vibrato);
+		}
 	}
+}
 
-	// vibrato
-	tmp = 0;
-	if (READ_LE_UINT16(instrumentData + 18) != 0)
-		tmp |= 0x80;
-	if (READ_LE_UINT16(instrumentData + 20) != 0)
-		tmp |= 0x40;
-	if (READ_LE_UINT16(instrumentData + 10) != 0)
-		tmp |= 0x20;
-	if (READ_LE_UINT16(instrumentData + 22) != 0)
-		tmp |= 0x10;
-	tmp |= (READ_LE_UINT16(instrumentData + 2) & 0xF);
-	snd_adlibWriteData(ADLIB_REG_AM_VIBRATO_EG_KS + adlibOp2, tmp);
+void AdlibSoundDriver::stopSound() {
+	int i;
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 63);
+	}
+	for (i = 0; i < 9; ++i) {
+		OPLWriteReg(_opl, 0xB0 | i, 0);
+	}
+	OPLWriteReg(_opl, 0xBD, 0);
+}
 
-	// key scaling
-	tmp = 0x3F - (READ_LE_UINT16(instrumentData + 16) & 0x3F);
-	tmp = snd_adlibChannelVolume[channelNum] * tmp;
-	tmp += tmp + 0x7F;
-	tmp = 0x3F - (tmp / 0xFE);
-	tmp |= READ_LE_UINT16(instrumentData) << 6;
-	snd_adlibWriteData(ADLIB_REG_KEY_SCALING_OPERATOR_OUTPUT + adlibOp2, tmp);
+int AdlibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
+	update(buffer, numSamples / 2);
+	// convert mono to stereo
+	for (int i = numSamples / 2 - 1; i >= 0; i--) {
+		buffer[2 * i] = buffer[2 * i + 1] = buffer[i];
+	}
+	return numSamples;
+}
 
-	// attack/decay rates */
-	tmp =(READ_LE_UINT16(instrumentData + 6) << 4) | (READ_LE_UINT16(instrumentData + 12) & 0xF);
-	snd_adlibWriteData(ADLIB_REG_ATTACK_RATE_DECAY_RATE + adlibOp2, tmp);
+void AdlibSoundDriver::initCard() {
+	_vibrato = 0x20;
+	OPLWriteReg(_opl, 0xBD, _vibrato);
+	OPLWriteReg(_opl, 0x08, 0x40);
+	
+	int i;
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 0);
+	}
+	for (i = 0; i < 9; ++i) {
+		OPLWriteReg(_opl, 0xB0 | i, 0);
+	}
+	for (i = 0; i < 9; ++i) {
+		OPLWriteReg(_opl, 0xC0 | i, 0);
+	}
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0x60 | _operatorsTable[i], 0);
+	}
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0x80 | _operatorsTable[i], 0);
+	}
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0x20 | _operatorsTable[i], 0);
+	}
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0xE0 | _operatorsTable[i], 0);
+	}
 
-	// sustain/release rates */
-	tmp = (READ_LE_UINT16(instrumentData + 8) << 4) | (READ_LE_UINT16(instrumentData + 14) & 0xF);
-	snd_adlibWriteData(ADLIB_REG_SUSTAIN_LEVEL_RELEASE_RATE_0 + adlibOp2, tmp);
-	snd_adlibWriteData(ADLIB_REG_WAVE_SELECT + adlibOp2, waveSelect2);
+	OPLWriteReg(_opl, 1, 0x20);
+	OPLWriteReg(_opl, 1, 0);
 }
 
-static void snd_adlibInterrupt(void *param, int16 *buf, int len) {
-	int16 *origData = buf;
-	uint origLen = len;
+void AdlibSoundDriver::update(int16 *buf, int len) {
 	static int samplesLeft = 0;
-
 	while (len != 0) {
-		int count;
+		int count = samplesLeft;
+		if (count > len) {
+			count = len;
+		}
+		samplesLeft -= count;
+		len -= count;
+		YM3812UpdateOne(_opl, buf, count);
 		if (samplesLeft == 0) {
-			if (snd_songIsPlaying || (snd_fadeOutCounter != 0 && snd_fadeOutCounter < 100)) {
-				++snd_songTicksCounter;
-				if (snd_songTicksCounter > snd_eventsDelay) {
-					snd_handleEvents();
-					snd_songTicksCounter = 0;
-				}
+			if (_upCb) {
+				(*_upCb)(_upRef);
 			}
-			samplesLeft = g_cine_adlib->getRate() / 50;
+			samplesLeft = _sampleRate / 50;
 		}
-		count = samplesLeft;
-		if (count > len)
-			count = len;
-
-		YM3812UpdateOne(g_cine_adlib->getOPL(), buf, count);
-
-		samplesLeft -= count;
-		len -= count;
 		buf += count;
 	}
-
-	// Convert mono data to stereo
-	for (int i = (origLen - 1); i >= 0; i--) {
-		origData[2 * i] = origData[2 * i + 1] = origData[i];
-	}
 }
 
-static void snd_adlibDriverSetupChannel(int channelNum, const uint8 *data, int instrumentNum) {
-	int16 vol = snd_sfxState.songData[instrumentNum];
-	if (vol != 0 && vol < 0x50)
-		vol = 0x50;
+void AdlibSoundDriver::setupInstrument(const uint8 *data, int channel) {
+	assert(channel < 4);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	loadInstrument(data, ins);
 
-	vol -= snd_fadeOutCounter;
-	if (vol < 0)
-		vol = 0;
+	int mod, car, tmp;
+	const AdlibRegisterSoundInstrument *reg;
 
-	vol += vol / 4;
-	if (vol > 0x7F)
-		vol = 0x7F;
+	if (ins->mode != 0)  {
+		mod = _operatorsTable[_voiceOperatorsTable[2 * ins->channel + 0]];
+		car = _operatorsTable[_voiceOperatorsTable[2 * ins->channel + 1]];
+	} else {
+		mod = _operatorsTable[_voiceOperatorsTable[2 * channel + 0]];
+		car = _operatorsTable[_voiceOperatorsTable[2 * channel + 1]];
+	}
+	
+	if (ins->mode == 0 || ins->channel == 6) {
+		reg = &ins->regMod;
+		OPLWriteReg(_opl, 0x20 | mod, reg->vibrato);
+		if (reg->freqMod) {
+			tmp = reg->outputLevel & 0x3F;
+		} else {
+			tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel];
+			tmp = 63 - (2 * tmp + 127) / (2 * 127);
+		}
+		OPLWriteReg(_opl, 0x40 | mod, tmp | (reg->keyScaling << 6));
+		OPLWriteReg(_opl, 0x60 | mod, reg->attackDecay);
+		OPLWriteReg(_opl, 0x80 | mod, reg->sustainRelease);
+		if (ins->mode != 0) {
+			OPLWriteReg(_opl, 0xC0 | ins->channel, reg->feedbackStrength);
+		} else {
+			OPLWriteReg(_opl, 0xC0 | channel, reg->feedbackStrength);
+		}
+		OPLWriteReg(_opl, 0xE0 | mod, ins->waveSelectMod);
+	}
 
-	snd_adlibChannelVolume[channelNum] = vol;
-	snd_adlibDriverSetupInstrument(data, channelNum);
+	reg = &ins->regCar;
+	OPLWriteReg(_opl, 0x20 | car, reg->vibrato);
+	tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel];
+	tmp = 63 - (2 * tmp + 127) / (2 * 127);
+	OPLWriteReg(_opl, 0x40 | car, tmp | (reg->keyScaling << 6));
+	OPLWriteReg(_opl, 0x60 | car, reg->attackDecay);
+	OPLWriteReg(_opl, 0x80 | car, reg->sustainRelease);
+	OPLWriteReg(_opl, 0xE0 | car, ins->waveSelectCar);
 }
 
-static void snd_getAdlibFrequency(int frequency, int *adlibFreq) {
-	int i;
+void AdlibSoundDriver::loadRegisterInstrument(const uint8 *data, AdlibRegisterSoundInstrument *reg) {
+	reg->vibrato = 0;
+	if (READ_LE_UINT16(data + 18)) { // amplitude vibrato
+		reg->vibrato |= 0x80;
+	}
+	if (READ_LE_UINT16(data + 20)) { // frequency vibrato
+		reg->vibrato |= 0x40;
+	}
+	if (READ_LE_UINT16(data + 10)) { // sustaining sound
+		reg->vibrato |= 0x20;
+	}
+	if (READ_LE_UINT16(data + 22)) { // envelope scaling
+		reg->vibrato |= 0x10;
+	}
+	reg->vibrato |= READ_LE_UINT16(data + 2) & 0xF; // frequency multiplier
+	
+	reg->attackDecay = READ_LE_UINT16(data + 6) << 4; // attack rate
+	reg->attackDecay |= READ_LE_UINT16(data + 12) & 0xF; // decay rate
+	
+	reg->sustainRelease = READ_LE_UINT16(data + 8) << 4; // sustain level
+	reg->sustainRelease |= READ_LE_UINT16(data + 14) & 0xF; // release rate
+	
+	reg->feedbackStrength = READ_LE_UINT16(data + 4) << 1; // feedback
+	if (READ_LE_UINT16(data + 24) == 0) { // frequency modulation
+		reg->feedbackStrength |= 1;
+	}
+	
+	reg->keyScaling = READ_LE_UINT16(data);
+	reg->outputLevel = READ_LE_UINT16(data + 16);
+	reg->freqMod = READ_LE_UINT16(data + 24);
+}
 
-	*adlibFreq = 95;
-	for (i = 0; i < 96; ++i) {
-		if (snd_adlibNoteFreqTable[i] <= frequency) {
-			*adlibFreq = i;
-			break;
+void AdlibSoundDriverINS::loadInstrument(const uint8 *data, AdlibSoundInstrument *asi) {
+	asi->mode = *data++;
+	asi->channel = *data++;
+	loadRegisterInstrument(data, &asi->regMod); data += 26;
+	loadRegisterInstrument(data, &asi->regCar); data += 26;
+	asi->waveSelectMod = data[0] & 3; data += 2;
+	asi->waveSelectCar = data[0] & 3; data += 2;
+	asi->amDepth = data[0]; data += 2;
+}
+
+void AdlibSoundDriverINS::setChannelFrequency(int channel, int frequency) {
+	assert(channel < 4);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	if (ins) {
+		if (ins->mode != 0 && ins->channel == 6) {
+			channel = 6;
 		}
+		if (ins->mode == 0 || ins->channel == 6) {
+			int freq, note, oct;
+			findNote(frequency, &note, &oct);
+			if (channel == 6) {
+				note %= 12;
+			}
+			freq = _freqTable[note % 12];
+			OPLWriteReg(_opl, 0xA0 | channel, freq);
+			freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
+			if (ins->mode == 0) {
+				freq |= 0x20;
+			}
+			OPLWriteReg(_opl, 0xB0 | channel, freq);
+		}
+		if (ins->mode != 0) {
+			_vibrato |= 1 << (10 - ins->channel);
+			OPLWriteReg(_opl, 0xBD, _vibrato);
+		}
 	}
 }
 
-static void snd_adlibDriverSetChannelFrequency(int channelNum, int frequency) {
-	const uint8 *instr = snd_adlibInstrumentsTable[channelNum];
-	uint8 fl = *instr++;	// var2
-	uint8 ch = *instr++;	// var1
-
-	if (fl != 0 && ch == 6)
-		channelNum = 6;
-
-	if (fl == 0 || channelNum == 6) {
-		uint16 freqLow, freqHigh;	// var8
-		int adlibFreq;
-
-		snd_getAdlibFrequency(frequency, &adlibFreq);
-		if (channelNum == 6)
-			adlibFreq %= 12;
-
-		freqLow = snd_adlibFreqTable[adlibFreq % 12];
-		snd_adlibWriteData(ADLIB_REG_FREQUENCY_0 + channelNum, freqLow);
-		freqHigh = ((adlibFreq / 12) << 2) | ((freqLow & 0x300) >> 8);
-		if (fl == 0)
-			freqHigh |= 0x20;
-
-		snd_adlibWriteData(ADLIB_REG_KEY_ON_OCTAVE_FREQUENCY_0 + channelNum, freqHigh);
+void AdlibSoundDriverINS::playSound(const uint8 *data, int channel, int volume) {
+	assert(channel < 4);
+	_channelsVolumeTable[channel] = 127;
+	resetChannel(channel);
+	setupInstrument(data + 257, channel);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	if (ins->mode != 0 && ins->channel == 6) {
+		channel = 6;
 	}
-	if (fl != 0) {
-		snd_adlibVibrato |= 1 << (10 - ch);
-		snd_adlibWriteData(ADLIB_REG_AM_VIBRATO_RHYTHM, snd_adlibVibrato);
+	if (ins->mode == 0 || channel == 6) {
+		int freq = _freqTable[0];
+		OPLWriteReg(_opl, 0xA0 | channel, freq);
+		freq = 4 | ((freq & 0x300) >> 8);
+		if (ins->mode == 0) {
+			freq |= 0x20;
+		}
+		OPLWriteReg(_opl, 0xB0 | channel, freq);
 	}
+	if (ins->mode != 0) {
+		_vibrato = 1 << (10 - ins->channel);
+		OPLWriteReg(_opl, 0xBD, _vibrato);
+	}
 }
 
-static void snd_adlibDriverStopChannel(int channelNum) {
-	const uint8 *instr = snd_adlibInstrumentsTable[channelNum];
-	uint8 fl = *instr++;	// var2
-	uint8 ch = *instr++;	// var1
+void AdlibSoundDriverADL::loadInstrument(const uint8 *data, AdlibSoundInstrument *asi) {
+	asi->mode = *data++;
+	asi->channel = *data++;
+	asi->waveSelectMod = *data++ & 3;
+	asi->waveSelectCar = *data++ & 3;
+	asi->amDepth = *data++;
+	++data;
+	loadRegisterInstrument(data, &asi->regMod); data += 26;
+	loadRegisterInstrument(data, &asi->regCar); data += 26;
+}
 
-	if (fl != 0 && ch == 6)
-		channelNum = 6;
+void AdlibSoundDriverADL::setChannelFrequency(int channel, int frequency) {
+	assert(channel < 4);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	if (ins) {
+		if (ins->mode != 0) {
+			channel = ins->channel;
+			if (channel == 9) {
+				channel = 8;
+			} else if (channel == 10) {
+				channel = 7;
+			}
+		}
+		int freq, note, oct;
+		findNote(frequency, &note, &oct);
+		
+		note += oct * 12;
+		if (ins->amDepth) {
+			note = ins->amDepth;
+		}
+		if (note < 0) {
+			note = 0;
+		}
 
-	if (fl == 0 || channelNum == 6)
-		snd_adlibWriteData(ADLIB_REG_KEY_ON_OCTAVE_FREQUENCY_0 + channelNum, 0);
-
-	if (fl != 0) {
-		snd_adlibVibrato &= (1 << (10 - ch)) ^ 0xFF;
-		snd_adlibWriteData(ADLIB_REG_AM_VIBRATO_RHYTHM, snd_adlibVibrato);
+		freq = _freqTable[note % 12];
+		OPLWriteReg(_opl, 0xA0 | channel, freq);
+		freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
+		if (ins->mode == 0) {
+			freq |= 0x20;
+		}
+		OPLWriteReg(_opl, 0xB0 | channel, freq);
+		if (ins->mode != 0) {
+			_vibrato = 1 << (10 - channel);
+			OPLWriteReg(_opl, 0xBD, _vibrato);
+		}
 	}
 }
 
-static void snd_adlibDriverPlaySound(uint8 * data, int channelNum, int volume) {
-//  if (_snd_mute) return;
-	uint8 fl, ch;		// var2, var1
-
-	assert(channelNum < 4);
-	data += 257;
-	snd_adlibInstrumentsTable[channelNum] = data;
-	snd_resetChannel(channelNum);
-	snd_adlibChannelVolume[channelNum] = 0x7F;
-	snd_adlibDriverSetupInstrument(data, channelNum);
-	fl = *data++;
-	ch = *data++;
-
-	if (fl != 0 && ch == 6)
-		channelNum = 6;
-
-	if (fl == 0 || channelNum == 6) {
-		uint16 freqLow, freqHigh;
-		freqLow = snd_adlibFreqTable[0];
-		snd_adlibWriteData(ADLIB_REG_FREQUENCY_0 + channelNum, freqLow);
-		freqHigh = 4 | ((freqLow & 0x300) >> 8);
-		if (fl == 0)
-			freqHigh |= 0x20;
-
-		snd_adlibWriteData(ADLIB_REG_KEY_ON_OCTAVE_FREQUENCY_0 + channelNum, freqHigh);
+void AdlibSoundDriverADL::playSound(const uint8 *data, int channel, int volume) {
+	assert(channel < 4);
+	_channelsVolumeTable[channel] = 127;
+	setupInstrument(data, channel);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	if (ins->mode != 0 && ins->channel == 6) {
+		OPLWriteReg(_opl, 0xB0 | channel, 0);
 	}
-	if (fl != 0) {
-		snd_adlibVibrato = 1 << (10 - ch);
-		snd_adlibWriteData(ADLIB_REG_AM_VIBRATO_RHYTHM, snd_adlibVibrato);
+	if (ins->mode != 0) {
+		_vibrato = (1 << (10 - ins->channel)) ^ 0xFF;
+		OPLWriteReg(_opl, 0xBD, _vibrato);
 	}
+	if (ins->mode != 0) {
+		channel = ins->channel;
+		if (channel == 9) {
+			channel = 8;
+		} else if (channel == 10) {
+			channel = 7;
+		}
+	}
+	uint16 note = 48;
+	if (ins->amDepth) {
+		note = ins->amDepth;
+	}
+	int freq = _freqTable[note % 12];
+	OPLWriteReg(_opl, 0xA0 | channel, freq);
+	freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
+	if (ins->mode == 0) {
+		freq |= 0x20;
+	}
+	OPLWriteReg(_opl, 0xB0 | channel, freq);
+	if (ins->mode != 0) {
+		_vibrato = 1 << (10 - channel);
+		OPLWriteReg(_opl, 0xBD, _vibrato);
+	}
 }
 
-static SoundDriver snd_adlibDriver = {
-	&snd_adlibDriverSetupChannel,
-	&snd_adlibDriverSetChannelFrequency,
-	&snd_adlibDriverStopChannel,
-	&snd_adlibDriverPlaySound
+const int SoundDriver::_noteTable[] = {
+	0xEEE, 0xE17, 0xD4D, 0xC8C, 0xBD9, 0xB2F, 0xA8E, 0x9F7,
+	0x967, 0x8E0, 0x861, 0x7E8, 0x777, 0x70B, 0x6A6, 0x647,
+	0x5EC, 0x597, 0x547, 0x4FB, 0x4B3, 0x470, 0x430, 0x3F4,
+	0x3BB, 0x385, 0x353, 0x323, 0x2F6, 0x2CB, 0x2A3, 0x27D,
+	0x259, 0x238, 0x218, 0x1FA, 0x1DD, 0x1C2, 0x1A9, 0x191,
+	0x17B, 0x165, 0x151, 0x13E, 0x12C, 0x11C, 0x10C, 0x0FD,
+	0x0EE, 0x0E1, 0x0D4, 0x0C8, 0x0BD, 0x0B2, 0x0A8, 0x09F,
+	0x096, 0x08E, 0x086, 0x07E, 0x077, 0x070, 0x06A, 0x064,
+	0x05E, 0x059, 0x054, 0x04F, 0x04B, 0x047, 0x043, 0x03F,
+	0x03B, 0x038, 0x035, 0x032, 0x02F, 0x02C, 0x02A, 0x027,
+	0x025, 0x023, 0x021, 0x01F, 0x01D, 0x01C, 0x01A, 0x019,
+	0x017, 0x016, 0x015, 0x013, 0x012, 0x011, 0x010, 0x00F
 };
 
-void snd_adlibDriverStopSong() {
-	int i;
+const int SoundDriver::_noteTableCount = ARRAYSIZE(_noteTable);
 
-	for (i = 0; i < 18; ++i)
-		snd_adlibWriteData(ADLIB_REG_KEY_SCALING_OPERATOR_OUTPUT + snd_adlibOpTable[i], 0x3F);
+const int AdlibSoundDriver::_freqTable[] = {
+	0x157, 0x16C, 0x181, 0x198, 0x1B1, 0x1CB,
+	0x1E6, 0x203, 0x222, 0x243, 0x266, 0x28A
+};
 
-	for (i = 0; i < 9; ++i)
-		snd_adlibWriteData(ADLIB_REG_KEY_ON_OCTAVE_FREQUENCY_0 + i, 0);
+const int AdlibSoundDriver::_freqTableCount = ARRAYSIZE(_freqTable);
 
-	snd_adlibWriteData(ADLIB_REG_AM_VIBRATO_RHYTHM, 0);
-}
+const int AdlibSoundDriver::_operatorsTable[] = {
+	0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13,	16, 17, 18, 19, 20, 21
+};
 
-void snd_resetChannel(int channelNum) {
-	(*snd_driver.stopChannel) (channelNum);
-	if (snd_useAdlib)
-		snd_adlibDriverStopSong();
-}
+const int AdlibSoundDriver::_operatorsTableCount = ARRAYSIZE(_operatorsTable);
 
-AdlibMusic::AdlibMusic(Audio::Mixer *pMixer) {
-	_mixer = pMixer;
-	_sampleRate = pMixer->getOutputRate();
-	g_cine_adlib = this;
-	_opl = makeAdlibOPL(_sampleRate);
+const int AdlibSoundDriver::_voiceOperatorsTable[] = {
+	0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 16, 16, 14, 14, 17, 17, 13, 13
+};
 
-	snd_adlibVibrato = 0x20;
-	snd_adlibWriteData(ADLIB_REG_AM_VIBRATO_RHYTHM, snd_adlibVibrato);
-	snd_adlibWriteData(0x08, 0x40);
+const int AdlibSoundDriver::_voiceOperatorsTableCount = ARRAYSIZE(_voiceOperatorsTable);
 
-	int i;
-
-	for (i = 0; i < 18; ++i)
-		snd_adlibWriteData(ADLIB_REG_KEY_SCALING_OPERATOR_OUTPUT + snd_adlibOpTable[i], 0);
-
-	for (i = 0; i < 9; ++i)
-		snd_adlibWriteData(ADLIB_REG_KEY_ON_OCTAVE_FREQUENCY_0 + i, 0);
-
-	for (i = 0; i < 9; ++i)
-		snd_adlibWriteData(ADLIB_REG_FEEDBACK_STRENGTH_CONNECTION_TYPE + i, 0);
-
-	for (i = 0; i < 18; ++i)
-		snd_adlibWriteData(ADLIB_REG_ATTACK_RATE_DECAY_RATE + snd_adlibOpTable[i], 0);
-
-	for (i = 0; i < 18; ++i)
-		snd_adlibWriteData(ADLIB_REG_SUSTAIN_LEVEL_RELEASE_RATE_0 + snd_adlibOpTable[i], 0);
-
-	for (i = 0; i < 18; ++i)
-		snd_adlibWriteData(ADLIB_REG_AM_VIBRATO_EG_KS + snd_adlibOpTable[i], 0);
-
-	for (i = 0; i < 18; ++i)
-		snd_adlibWriteData(ADLIB_REG_WAVE_SELECT + snd_adlibOpTable[i],
-		    0);
-
-	snd_adlibWriteData(1, 0x20);
-	snd_adlibWriteData(1, 0);
-
-	for (i = 0; i < 4; ++i)
-		snd_adlibInstrumentsTable[i] = snd_nullInstrument;
-
-	snd_useAdlib = 1;
-	snd_driver = snd_adlibDriver;
-
-	_mixer->setupPremix(this);
-}
-
-void AdlibMusic::premixerCall(int16 *data, uint len) {
-	snd_adlibInterrupt(NULL, data, len);
-}
-
-void AdlibMusic::setVolume(uint8 volume) {
-	for (int i = 0; i < 4; ++i)
-		snd_adlibChannelVolume[i] = volume | 128;
-}
-
-AdlibMusic::~AdlibMusic(void) {
-	_mixer->setupPremix(NULL);
-}
-
 } // End of namespace Cine

Modified: scummvm/trunk/engines/cine/sound_driver.h
===================================================================
--- scummvm/trunk/engines/cine/sound_driver.h	2006-03-09 20:50:19 UTC (rev 21185)
+++ scummvm/trunk/engines/cine/sound_driver.h	2006-03-09 22:37:19 UTC (rev 21186)
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef CINE_SNDDRIVER_H_
-#define CINE_SNDDRIVER_H_
+#ifndef CINE_SOUNDDRIVER_H_
+#define CINE_SOUNDDRIVER_H_
 
 #include "sound/audiostream.h"
 #include "sound/fmopl.h"
@@ -33,62 +33,111 @@
 }
 
 namespace Cine {
+	
+class SoundDriver {
+public:
+	typedef void (*UpdateCallback)(void *);
 
-#define ADLIB_REG_TIMER_1_DATA 2
-#define ADLIB_REG_TIMER_CONTROL_FLAGS 4
-#define ADLIB_REG_AM_VIBRATO_EG_KS 0x20
-#define ADLIB_REG_KEY_SCALING_OPERATOR_OUTPUT 0x40
-#define ADLIB_REG_ATTACK_RATE_DECAY_RATE 0x60
-#define ADLIB_REG_SUSTAIN_LEVEL_RELEASE_RATE_0 0x80
-#define ADLIB_REG_FREQUENCY_0 0xA0
-#define ADLIB_REG_KEY_ON_OCTAVE_FREQUENCY_0 0xB0
-#define ADLIB_REG_AM_VIBRATO_RHYTHM 0xBD
-#define ADLIB_REG_FEEDBACK_STRENGTH_CONNECTION_TYPE 0xC0
-#define ADLIB_REG_WAVE_SELECT 0xE0
+	virtual void setupChannel(int channel, const uint8 *data, int instrument, int volume) = 0;
+	virtual void setChannelFrequency(int channel, int frequency) = 0;
+	virtual void stopChannel(int channel) = 0;
+	virtual void playSound(const uint8 *data, int channel, int volume) = 0;
+	virtual void stopSound() = 0;
+	virtual const char *getInstrumentExtension() const = 0;
+	
+	void setUpdateCallback(UpdateCallback upCb, void *ref);
+	void resetChannel(int channel);
+	void findNote(int freq, int *note, int *oct) const;
 
-struct SoundDriver {
-	void (*setupChannel) (int channelNum, const uint8 * data, int instrumentNum);
-	void (*setChannelFrequency) (int channelNum, int frequency);
-	void (*stopChannel) (int channelNum);
-	void (*playSound) (uint8 * data, int channelNum, int volume);
+protected:
+	UpdateCallback _upCb;
+	void *_upRef;
+
+	static const int _noteTable[];
+	static const int _noteTableCount;
 };
 
-extern uint16 snd_fadeOutCounter, snd_songTicksCounter;
-extern uint8 *snd_adlibInstrumentsTable[4];
-extern SoundDriver snd_driver;
+struct AdlibRegisterSoundInstrument {
+	uint16 vibrato;
+	uint16 attackDecay;
+	uint16 sustainRelease;
+	uint16 feedbackStrength;
+	uint16 keyScaling;
+	uint16 outputLevel;
+	uint16 freqMod;
+};
 
-extern void snd_adlibDriverInit();
-extern void snd_adlibDriverExit();
-extern void snd_adlibDriverStopSong();
-extern void snd_resetChannel(int channelNum);
-
-class AdlibMusic : public AudioStream {
+struct AdlibSoundInstrument {
+	uint8 mode;
+	uint8 channel;
+	AdlibRegisterSoundInstrument regMod;
+	AdlibRegisterSoundInstrument regCar;
+	uint8 waveSelectMod;
+	uint8 waveSelectCar;
+	uint8 amDepth;
+};
+	
+class AdlibSoundDriver : public SoundDriver, AudioStream {
 public:
-	AdlibMusic(Audio::Mixer * pMixer);
-	~AdlibMusic(void);
-	virtual void setVolume(uint8 volume);
+	AdlibSoundDriver(Audio::Mixer *mixer);
+	virtual ~AdlibSoundDriver();
 
-	FM_OPL *getOPL() {
-		return _opl;
-	}
+	// SoundDriver interface
+	virtual void setupChannel(int channel, const uint8 *data, int instrument, int volume);
+	virtual void stopChannel(int channel);
+	virtual void stopSound();
 
-	// AudioStream API
-	int readBuffer(int16 *buffer, const int numSamples) {
-		premixerCall(buffer, numSamples / 2);
-		return numSamples;
-	}
-	bool isStereo() const { return true; }
-	bool endOfData() const { return false; }
-	int getRate() const { return _sampleRate; }
+	// AudioStream interface
+	virtual int readBuffer(int16 *buffer, const int numSamples);
+	virtual bool isStereo() const { return true; }
+	virtual bool endOfData() const { return false; }
+	virtual int getRate() const { return _sampleRate; }
 
-private:
+	void initCard();
+	void update(int16 *buf, int len);
+	void setupInstrument(const uint8 *data, int channel);
+	void loadRegisterInstrument(const uint8 *data, AdlibRegisterSoundInstrument *reg);
+	virtual void loadInstrument(const uint8 *data, AdlibSoundInstrument *asi) = 0;
+
+protected:
 	FM_OPL *_opl;
-	Audio::Mixer * _mixer;
-	uint32 _sampleRate;
+	int _sampleRate;
+	Audio::Mixer *_mixer;
 
-	void premixerCall(int16 *buf, uint len);
+	uint8 _vibrato;
+	int _channelsVolumeTable[4];
+	AdlibSoundInstrument _instrumentsTable[4];
+
+	static const int _freqTable[];
+	static const int _freqTableCount;
+	static const int _operatorsTable[];
+	static const int _operatorsTableCount;
+	static const int _voiceOperatorsTable[];
+	static const int _voiceOperatorsTableCount;
 };
 
+// Future Wars adlib driver
+class AdlibSoundDriverINS : public AdlibSoundDriver {
+public:
+	AdlibSoundDriverINS(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {}
+	virtual const char *getInstrumentExtension() const { return ".INS"; }
+	virtual void loadInstrument(const uint8 *data, AdlibSoundInstrument *asi);
+	virtual void setChannelFrequency(int channel, int frequency);
+	virtual void playSound(const uint8 *data, int channel, int volume);
+};
+
+// Operation Stealth adlib driver
+class AdlibSoundDriverADL : public AdlibSoundDriver {
+public:
+	AdlibSoundDriverADL(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {}
+	virtual const char *getInstrumentExtension() const { return ".ADL"; }
+	virtual void loadInstrument(const uint8 *data, AdlibSoundInstrument *asi);
+	virtual void setChannelFrequency(int channel, int frequency);
+	virtual void playSound(const uint8 *data, int channel, int volume);
+};
+
+extern SoundDriver *g_soundDriver; // TEMP
+
 } // End of namespace Cine
 
-#endif				/* CINE_SNDDRIVER_H_ */
+#endif /* CINE_SOUNDDRIVER_H_ */

Modified: scummvm/trunk/engines/cine/various.cpp
===================================================================
--- scummvm/trunk/engines/cine/various.cpp	2006-03-09 20:50:19 UTC (rev 21185)
+++ scummvm/trunk/engines/cine/various.cpp	2006-03-09 22:37:19 UTC (rev 21186)
@@ -153,10 +153,6 @@
 
 selectedObjStruct currentSelectedObject;
 
-void stopSample(void) {
-	snd_stopSong();
-}
-
 void mainLoopSub3(void) {
 }
 
@@ -475,7 +471,7 @@
 		return -1;
 	}
 
-	stopSample();
+	g_sfxPlayer->stop();
 	closeEngine3();
 	unloadAllMasks();
 	freePrcLinkedList();


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