Ticket #8757: kyraSoundTownsEtc.patch

File kyraSoundTownsEtc.patch, 42.7 KB (added by athrxx, 16 years ago)

FM-Towns Music Patch for Kyra

  • detection.cpp

     
    5151
    5252#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, Kyra::GI_KYRA2)
    5353#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, Kyra::GI_KYRA2)
     54#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, Kyra::GI_KYRA2)
     55#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, Kyra::GI_KYRA2)
    5456
    5557#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, Kyra::GI_KYRA3)
    5658
     
    176178                {
    177179                        "kyra1",
    178180                        0,
    179                         AD_ENTRY1("TWMUSIC.PAK", "e53bca3a3e3fb49107d59463ec387a59"),
     181                        {
     182                                { "EMC.PAK", 0, "a046bb0b422061aab8e4c4689400343a", -1 },
     183                                { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 },
     184                                { NULL, 0, NULL, 0 }
     185                        },
    180186                        Common::EN_ANY,
    181187                        Common::kPlatformFMTowns,
    182188                        Common::ADGF_NO_FLAGS
     
    187193                {
    188194                        "kyra1",
    189195                        0,
    190                         AD_ENTRY1("TWMUSIC.PAK", "e53bca3a3e3fb49107d59463ec387a59"),
     196                        {
     197                                { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 },
     198                                { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 },
     199                                { NULL, 0, NULL, 0 }
     200                        },
    191201                        Common::JA_JPN,
    192202                        Common::kPlatformFMTowns,
    193203                        Common::ADGF_NO_FLAGS
     
    332342
    333343        {
    334344                {
     345                        "kyra2",
     346                                0,
     347                                AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"),
     348                                Common::EN_ANY,
     349                                Common::kPlatformFMTowns,
     350                                Common::ADGF_NO_FLAGS
     351                },
     352                KYRA2_TOWNS_FLAGS
     353        },
     354
     355        {
     356                {
     357                        "kyra2",
     358                                0,
     359                                AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"),
     360                                Common::JA_JPN,
     361                                Common::kPlatformFMTowns,
     362                                Common::ADGF_NO_FLAGS
     363                },
     364                KYRA2_TOWNS_SJIS_FLAGS
     365        },
     366
     367        {
     368                {
    335369                        "kyra3",
    336370                        0,
    337371                        AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"),
     
    402436        bool res = true;
    403437
    404438        Kyra::GameFlags flags = gd->flags;
    405        
     439
    406440        flags.lang = gd->desc.language;
    407441        flags.platform = gd->desc.platform;
    408442
  • kyra.cpp

     
    9494
    9595        if (_flags.platform == Common::kPlatformFMTowns) {
    9696                // TODO: later on here should be a usage of MixedSoundDriver
    97                 _sound = new SoundTowns(this, _mixer);
     97                if (_flags.gameID == GI_KYRA1)
     98                        _sound = new SoundTowns(this, _mixer);
     99                else
     100                        _sound = new SoundTowns_v2(this, _mixer);
    98101        } else if (_flags.platform == Common::kPlatformPC98) {
    99102                // TODO: currently we don't support the PC98 sound data,
    100103                // but since it has the FM-Towns data files, we just use the
  • kyra_v2.cpp

     
    3636
    3737#include "common/system.h"
    3838
     39#if _MSC_VER >= 1400
     40#define sprintf                 sprintf_s
     41#define strcpy(a, b)    strcpy_s((a), strlen((b)) + 1, (b))
     42#define strcat(a, b)    strcat_s((a), strlen((a)) + strlen((b)) + 1, (b))
     43#endif
     44
    3945namespace Kyra {
    4046
    4147KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags), _updateFunctor(this, &KyraEngine_v2::update) {
     
    113119
    114120        KyraEngine::init();
    115121
     122        if (!_sound->init())
     123                error("Couldn't init sound");
     124
    116125        _debugger = new Debugger_v2(this);
    117126        assert(_debugger);
    118127        _text = new TextDisplayer_v2(this, _screen);
     
    145154        }
    146155
    147156        for (int i = 0; i < 33; i++)
    148                 _sequenceStringsDuration[i] = strlen(_sequenceStrings[i]) * 8;
     157                _sequenceStringsDuration[i] = (int) strlen(_sequenceStrings[i]) * 8;
    149158
    150159        // No mouse display in demo
    151160        if (_flags.isDemo)
     
    164173}
    165174
    166175int KyraEngine_v2::go() {
    167         // Temporary measure to work around the fact that there's
    168         // several WSA files with identical names in different PAK files.
    169         _res->unloadPakFile("OUTFARM.PAK");
    170         _res->unloadPakFile("FLYTRAP.PAK");
     176        if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
     177                seq_showStarcraftLogo();
    171178
    172179        seq_playSequences(kSequenceVirgin, kSequenceZanfaun);
    173180        //seq_playSequences(kSequenceFunters, kSequenceFrash);
     
    175182        if (_menuChoice == 1) {
    176183                // load just the pak files needed for ingame
    177184                _res->unloadAllPakFiles();
    178                 _res->loadFileList("FILEDATA.FDT");
     185                if (_flags.isTalkie) {
     186                        _res->loadFileList("FILEDATA.FDT");
     187                } else {
     188                        char tmpfilename[13];
     189                        static const char * pakfiles [] = { "KYRA.DAT", "AUDIO.PAK", "CAULDRON.PAK",
     190                                "MISC_CPS.PAK", "MISC_EMC.PAK", "OTHER.PAK", "VOC.PAK", "WSCORE.PAK" };
     191                        for (int i = 0; i < 8; i++)
     192                                _res->loadPakFile(pakfiles[i]);
     193                        for (int i = 1; i < 10; i++) {
     194                                sprintf(tmpfilename, "COST%d_SH.PAK", i);
     195                                _res->loadPakFile(tmpfilename);
     196                        }
     197                        for (int i = 1; i < 6; i++) {
     198                                sprintf(tmpfilename, "HOFCH_%d.PAK", i);
     199                                _res->loadPakFile(tmpfilename);
     200                        }
     201                }
     202
    179203                startup();
    180204                runLoop();
    181205                cleanup();
     
    187211}
    188212
    189213void KyraEngine_v2::startup() {
    190         _sound->setSoundFileList(_dosSoundFileList, _dosSoundFileListSize);
     214        snd_assignMusicData(k2MusicIngame);
     215        // The track map is exactly the same
     216        // for FM-TOWNS and DOS
    191217        _trackMap = _dosTrackMap;
    192218        _trackMapSize = _dosTrackMapSize;
    193219
     
    306332                //      waitTicks(5);
    307333                //      sub_270A0();
    308334                //}
    309                
     335
    310336                if (_system->getMillis() > _nextIdleAnim)
    311337                        showIdleAnim();
    312338
     
    15401566        _sound->loadSoundFile(file);
    15411567}
    15421568
     1569void KyraEngine_v2::snd_assignMusicData(k2MusicDataID id) {
     1570        if (_flags.isTalkie) {
     1571                if (id == k2MusicIntro)
     1572                        _sound->setSoundFileList(_dosSoundFileListIntro, 1);
     1573                else if (id == k2MusicFinale)
     1574                        _sound->setSoundFileList(_dosSoundFileListFinale, 1);
     1575                else
     1576                        _sound->setSoundFileList(_dosSoundFileList, _dosSoundFileListSize);
     1577        } else {
     1578                ((SoundTowns_v2*)_sound)->assignMusicData((int) id);
     1579        }
     1580}
     1581
    15431582void KyraEngine_v2::playVoice(int high, int low) {
    15441583        int vocFile = high * 10000 + low * 10;
    15451584        snd_playVoiceFile(vocFile);
     
    16321671                case 48:
    16331672                        snd_playSoundEffect(0x38);
    16341673                        break;
    1635                
     1674
    16361675                default:
    16371676                        break;
    16381677                }
     
    19041943
    19051944} // end of namespace Kyra
    19061945
    1907 
     1946#if _MSC_VER >= 1400
     1947#undef  sprintf
     1948#undef  strcpy
     1949#undef  strcat
     1950#endif
     1951 No newline at end of file
  • kyra_v2.h

     
    7474        kSequenceHand4
    7575};
    7676
     77enum k2MusicDataID {
     78        k2MusicIntro = 0,
     79        k2MusicIngame,
     80        k2MusicFinale
     81};
    7782class WSAMovieV2;
    7883class KyraEngine_v2;
    7984class TextDisplayer_v2;
     
    225230        void seq_printCreditsString(uint16 strIndex, int x, int y, uint8 * colorMap, uint8 textcolor);
    226231        void seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width,
    227232                WSAMovieV2 * wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos);
     233        int seq_generateFixedRandomValue(int rangeFirst, int rangeLast);
     234        void seq_showStarcraftLogo();
    228235
    229236        void seq_init();
    230237        void seq_uninit();
     
    246253        static const int8 _dosTrackMap[];
    247254        static const int _dosTrackMapSize;
    248255
    249         static const char *_introSoundList[];
    250         static const int _introSoundListSize;
    251         static const char *_introStrings[];
    252         static const int _introStringsSize;
    253 
    254         int _introStringsDuration[21];
    255 
    256256protected:
    257257        // game initialization
    258258        void startup();
     
    628628
    629629        virtual void snd_playVoiceFile(int id);
    630630        void snd_loadSoundFile(int id);
     631        void snd_assignMusicData(k2MusicDataID id);
    631632
    632633        void playVoice(int high, int low);
    633634
     
    639640        void timerFunc6(int);
    640641
    641642        void setTimer1DelaySecs(int secs);
    642        
     643
    643644        uint32 _nextIdleAnim;
    644645        int _lastIdleScript;
    645646
     
    846847        static const int _sequenceStringsSize_TOWNS_EN;
    847848        static const char *_sequenceStrings_PC_EN[];
    848849        static const int _sequenceStringsSize_PC_EN;
     850        static const char _actorScreenStrings_PC_EN[];
     851        static const int _actorScreenStringsSize_PC_EN;
    849852
    850853        int _sequenceStringsDuration[33];
    851854
     
    861864        int _seqFrameCounter;
    862865        int _seqWsaCurrentFrame;
    863866        bool _seqSpecialFlag;
     867        int _seqRandomizeBase;
    864868        bool _seqSubframePlaying;
    865869        uint8 _seqTextColor[2];
    866870        uint8 _seqTextColorMap[16];
  • sequences_v2.cpp

     
    5353                };
    5454                _sound->setSoundFileList(soundFileList, 2);
    5555        } else {
    56                 const char *const *soundFileList =
    57                         (startSeq > kSequenceZanfaun) ? _dosSoundFileListFinale : _dosSoundFileListIntro;
    58                 _sound->setSoundFileList(soundFileList, 1);
     56                snd_assignMusicData((startSeq > kSequenceZanfaun) ?     k2MusicFinale : k2MusicIntro);
    5957        }
    6058        _sound->loadSoundFile(0);
    6159
     
    14451443}
    14461444
    14471445int KyraEngine_v2::seq_finaleFrash(WSAMovieV2 *wsaObj, int x, int y, int frm) {
    1448         //uint32 endtime = 0;
    14491446        int tmp = 0;
    14501447
    14511448        switch (frm) {
     
    14621459                case -1:
    14631460                        // if (_flags.isTalkie)
    14641461                        //       seq_finaleActorScreen();
    1465                         _seqSpecialFlag = true;
     1462                        _seqSpecialFlag = _flags.isTalkie;
     1463                        _seqRandomizeBase = 1;
    14661464                        break;
    14671465
    14681466                case 0:
     
    14801478                        if (_seqFrameCounter < 20 && _seqSpecialFlag) {
    14811479                                _seqWsaCurrentFrame = 0;
    14821480                        } else {
    1483                                 _seqFrameDelay = 500;
     1481                                _seqFrameDelay = _flags.isTalkie ? 500 : (300 + seq_generateFixedRandomValue(1, 300));
    14841482                                seq_playTalkText(_flags.isTalkie ? 26 : 22);
    14851483                                if (_seqSpecialFlag) {
    14861484                                        _seqFrameCounter = 3;
     
    14951493
    14961494                case 3:
    14971495                        seq_playTalkText(_flags.isTalkie ? 27 : 23);
    1498                         _seqFrameDelay = 500;
     1496                        _seqFrameDelay = _flags.isTalkie ? 500 : (300 + seq_generateFixedRandomValue(1, 300));
    14991497                        break;
    15001498
    15011499                case 4:
     
    15061504                        seq_playTalkText(_flags.isTalkie ? 27 : 23);
    15071505                        tmp = _seqFrameCounter / 6;
    15081506                        if (tmp == 2)
    1509                                 _seqFrameDelay = 7;
     1507                                _seqFrameDelay = _flags.isTalkie ? 7 : (1 + seq_generateFixedRandomValue(1, 10));
    15101508                        else if (tmp < 2)
    1511                                 _seqFrameDelay = 500;
     1509                                _seqFrameDelay = _flags.isTalkie ? 500 : (300 + seq_generateFixedRandomValue(1, 300));
    15121510                        break;
    15131511
    15141512                case 6:
     
    15431541        _screen->loadBitmap("finale.cps", 3, 3, _screen->_currentPalette);
    15441542        _screen->setFont(Screen::FID_GOLDFONT_FNT);
    15451543
    1546         _sound->setSoundFileList(_dosSoundFileList, _dosSoundFileListSize);
     1544        snd_assignMusicData(k2MusicIngame);
    15471545        _sound->loadSoundFile(3);
    15481546        _sound->playTrack(3);
    15491547
     
    15521550
    15531551        // TODO
    15541552
    1555         _sound->setSoundFileList(_dosSoundFileListFinale, 1);
     1553        snd_assignMusicData(k2MusicFinale);
    15561554        _sound->loadSoundFile(0);
    15571555}
    15581556
     
    20982096}
    20992097
    21002098void KyraEngine_v2::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, WSAMovieV2 * wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos) {
    2101         int dur = strlen(_sequenceStrings[strIndex]) * (_flags.isTalkie ? 7 : 15);
     2099        int dur = int(strlen(_sequenceStrings[strIndex])) * (_flags.isTalkie ? 7 : 15);
    21022100        int entry = seq_setTextEntry(strIndex, x, y, dur, width);
    21032101        _activeText[entry].textcolor = textColor;
    21042102        uint32 chatTimeout = _system->getMillis() + dur * _tickLength;
     
    21392137                curframe++;
    21402138        }
    21412139
    2142 
    2143 
    21442140        if (lastframe < 0) {
    21452141                int t = ABS(lastframe);
    21462142                if (t < curframe)
     
    21532149        _seqWsaCurrentFrame = curframe;
    21542150}
    21552151
     2152int KyraEngine_v2::seq_generateFixedRandomValue(int rangeFirst, int rangeLast) {
     2153        int result = 0;
     2154        if (rangeFirst > rangeFirst)
     2155                SWAP(rangeFirst, rangeLast);
     2156        int range = (rangeLast - rangeFirst) + 1;
     2157
     2158        do {
     2159                _seqRandomizeBase = _seqRandomizeBase * 1103515245 + 12345;
     2160                result = ((range * ((_seqRandomizeBase % 0x7fffffff) & 0x7fff)) / 32768) + rangeFirst;
     2161        } while (rangeLast < result);
     2162
     2163        return result;
     2164}
     2165
     2166void KyraEngine_v2::seq_showStarcraftLogo() {
     2167        WSAMovieV2 * ci = new WSAMovieV2(this);
     2168        assert(ci);
     2169        _screen->clearPage(2);
     2170        _res->loadPakFile("INTROGEN.PAK");
     2171        int endframe = ci->open("ci.wsa", 0, _screen->_currentPalette);
     2172        _res->unloadPakFile("INTROGEN.PAK");
     2173        if (!ci->opened()) {
     2174                delete ci;
     2175                return;
     2176        }
     2177        _screen->hideMouse();
     2178        ci->setX(0);
     2179        ci->setY(0);
     2180        ci->setDrawPage(2);
     2181        ci->displayFrame(0, 0);
     2182        _screen->copyPage(2, 0);
     2183        _screen->fadeFromBlack();
     2184        for (int i = 1; i < endframe; i++) {
     2185                if (_skipFlag)
     2186                        break;
     2187                ci->displayFrame(i, 0);
     2188                _screen->copyPage(2, 0);
     2189                _screen->updateScreen();
     2190                delay(50);
     2191        }
     2192        if(!_skipFlag) {
     2193                ci->displayFrame(0, 0);
     2194                _screen->copyPage(2, 0);
     2195                _screen->updateScreen();
     2196                delay(50);
     2197        }
     2198        _screen->fadeToBlack();
     2199        _screen->showMouse();
     2200
     2201        _skipFlag = false;
     2202        delete ci;
     2203}
     2204
    21562205void KyraEngine_v2::seq_init() {
    21572206        _seqProcessedString = new char[200];
    21582207        _seqWsa = new WSAMovieV2(this);
    21592208        _activeWSA = new ActiveWSA[8];
    21602209        _activeText = new ActiveText[10];
     2210
     2211        _res->unloadAllPakFiles();
     2212        _res->loadPakFile("KYRA.DAT");
     2213        _res->loadPakFile("AUDIO.PAK");
     2214        _res->loadPakFile("INTROGEN.PAK");
     2215        _res->loadPakFile("OTHER.PAK");
     2216        _res->loadPakFile("VOC.PAK");
     2217        if (_flags.isTalkie) {
     2218                _res->loadPakFile("TALKENG.PAK");
     2219                _res->loadPakFile("TALKGER.PAK");
     2220                _res->loadPakFile("TALKFRE.PAK");
     2221                _res->loadPakFile("INTROTLK.PAK");
     2222        } else if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
     2223                _res->loadPakFile("INTROVOC.PAK");
     2224                _res->loadPakFile("WSCORE.PAK");
     2225        }
    21612226}
    21622227
    21632228void KyraEngine_v2::seq_uninit() {
     
    21812246void KyraEngine_v2::seq_makeBookOrCauldronAppear(int type) {
    21822247        _screen->hideMouse();
    21832248        showMessage(0, 0xCF);
    2184        
     2249
    21852250        if (type == 1) {
    21862251                seq_makeBookAppear();
    21872252        } else if (type == 2) {
     
    21902255
    21912256        _screen->copyRegionToBuffer(2, 0, 0, 320, 200, _screenBuffer);
    21922257        _screen->loadBitmap("_PLAYALL.CPS", 3, 3, 0);
    2193        
     2258
    21942259        static int16 bookCauldronRects[] = {
    21952260                0x46, 0x90, 0x7F, 0x2B, // unknown rect (maybe unused?)
    21962261                0xCE, 0x90, 0x2C, 0x2C, // book rect
     
    22152280
    22162281void KyraEngine_v2::seq_makeBookAppear() {
    22172282        _screen->hideMouse();
    2218        
     2283
    22192284        displayInvWsaLastFrame();
    2220        
     2285
    22212286        showMessage(0, 0xCF);
    22222287
    22232288        loadInvWsa("BOOK2.WSA", 0, 4, 2, -1, -1, 0);
    2224        
     2289
    22252290        uint8 *rect = new uint8[_screen->getRectSize(_invWsa.w, _invWsa.h)];
    22262291        assert(rect);
    2227        
     2292
    22282293        _screen->copyRegionToBuffer(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect);
    22292294
    22302295        _invWsa.running = false;
     
    22362301
    22372302        while (true) {
    22382303                _invWsa.timer = _system->getMillis() + _invWsa.delay * _tickLength;
    2239                
     2304
    22402305                _screen->copyBlockToPage(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect);
    22412306
    22422307                _invWsa.wsa->displayFrame(_invWsa.curFrame, 0x4000, 0, 0);
    22432308
    22442309                if (_invWsa.page)
    22452310                        _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, _invWsa.page, 0, Screen::CR_NO_P_CHECK);
    2246                
     2311
    22472312                ++_invWsa.curFrame;
    22482313
    22492314                if (_invWsa.curFrame >= _invWsa.lastFrame && !_quitFlag)
    22502315                        break;
    2251                
     2316
    22522317                switch (_invWsa.curFrame) {
    22532318                case 39:
    22542319                        snd_playSoundEffect(0xCA);
  • sound.h

     
    5959
    6060namespace Kyra {
    6161
    62 /** 
     62/**
    6363 * Analog audio output device API for Kyrandia games.
    6464 * It countains functionallity to play music tracks,
    6565 * sound effects and voices.
     
    161161         *
    162162         * @param file  file to be played
    163163         */
    164         void voicePlay(const char *file);
     164        virtual void voicePlay(const char *file);
    165165
    166166        /**
    167167         * Checks if a voice is being played.
     
    213213 * Dune II, Kyrandia 1 and 2. While Dune II and
    214214 * Kyrandia 1 are using exact the same format, the
    215215 * one of Kyrandia 2 slightly differs.
    216  * 
     216 *
    217217 * See AdlibDriver for more information.
    218218 * @see AdlibDriver
    219219 */
     
    268268 *
    269269 * Currently it does not initialize the MT-32 output properly,
    270270 * so MT-32 output does sound a bit odd in some cases.
    271  * 
     271 *
    272272 * TODO: this code needs some serious cleanup and rework
    273273 * to support MT-32 and GM properly.
    274274 */
     
    341341        Common::Mutex _mutex;
    342342};
    343343
    344 class FMT_EuphonyDriver;
     344class SoundTowns_EuphonyDriver;
    345345class SoundTowns : public MidiDriver, public Sound {
    346346public:
    347347        SoundTowns(KyraEngine *vm, Audio::Mixer *mixer);
     
    350350        bool init();
    351351        void process();
    352352
    353         void setVolume(int) { /* TODO */ }
    354         int getVolume() { return 255; /* TODO */ }
     353        void setVolume(int) {}
     354        int getVolume() { return 255; }
    355355
     356        void setMusicVolume(int volume);
     357        void setSoundEffectsVolume(int volume) { _sfxVolume = (uint8) volume; }
     358
    356359        void loadSoundFile(uint file);
    357360
    358361        void playTrack(uint8 track);
     
    387390        Audio::AudioStream *_currentSFX;
    388391        Audio::SoundHandle _sfxHandle;
    389392
    390         int _currentTrackTable;
    391393        uint _sfxFileIndex;
    392394        uint8 *_sfxFileData;
     395        uint8 _sfxVolume;
    393396
    394         FMT_EuphonyDriver * _driver;
     397        SoundTowns_EuphonyDriver * _driver;
    395398        MidiParser * _parser;
    396         uint8 *_musicTrackData;
    397399
    398400        Common::Mutex _mutex;
    399401
    400         static const char *_sfxFiles[];
    401         static const int _sfxFilenum;
    402402        static const uint8 _sfxBTTable[256];
    403403        const uint8 *_sfxWDTable;
    404404};
    405405
     406} // end of namespace Kyra
     407
     408struct Kyra2AudioThemes {
     409        const uint8 * cdaTable;
     410        const uint8 cdaTableSize;
     411        const char * twnFilename;
     412};
     413
     414namespace Kyra {
     415
     416//class SoundTowns_v2_TwnDriver;
     417class SoundTowns_v2: public Sound {
     418public:
     419        SoundTowns_v2(KyraEngine *vm, Audio::Mixer *mixer);
     420        ~SoundTowns_v2();
     421
     422        bool init();
     423        void process();
     424
     425        void setVolume(int) {}
     426        int getVolume() { return 255; }
     427
     428        void setMusicVolume(int volume);
     429        void setSoundEffectsVolume(int volume) { _sfxVolume = (uint8) volume; }
     430
     431        void loadSoundFile(uint file) {}
     432        void assignMusicData (int id) { _currentTheme = id; }
     433
     434        void playTrack(uint8 track);
     435        void haltTrack();
     436        void beginFadeOut();
     437
     438        void voicePlay(const char *file);
     439        void playSoundEffect(uint8) {}
     440
     441private:
     442        int _lastTrack;
     443        int _currentTheme;
     444
     445        Audio::AudioStream *_currentSFX;
     446        Audio::SoundHandle _sfxHandle;
     447        uint8 _sfxVolume;
     448
     449        //SoundTowns_v2_TwnDriver * _driver;
     450        uint8 * _twnTrackData;
     451
     452        static const uint8 _cdaTrackTableK2Intro[];
     453        static const uint8 _cdaTrackTableK2Ingame[];
     454        static const uint8 _cdaTrackTableK2Finale[];
     455        static const Kyra2AudioThemes _themes[];
     456};
     457
    406458class MixedSoundDriver : public Sound {
    407459public:
    408460        MixedSoundDriver(KyraEngine *vm, Audio::Mixer *mixer, Sound *music, Sound *sfx) : Sound(vm, mixer), _music(music), _sfx(sfx) {}
  • sound_towns.cpp

     
    3333#include "sound/audiostream.h"
    3434
    3535#include "common/util.h"
     36
     37#if _MSC_VER >= 1400
     38#define         sprintf         sprintf_s
     39#endif
     40
    3641#include <math.h>
    3742
     43#define         EUPHONY_FADEOUT_TICKS           600
     44
    3845namespace Kyra {
    3946
    40 enum EuD_ChannelState { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing };
     47enum ChannelState { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing };
    4148
    4249class MidiChannel_EuD : public MidiChannel {
    4350public:
     
    125132                        const int8 *_samples;
    126133                } * _snd[8];
    127134                struct Env {
    128                         EuD_ChannelState state;
     135                        ChannelState state;
    129136                        int32 currentLevel;
    130137                        int32 rate;
    131138                        int32 tickCount;
     
    142149        } * _voice;
    143150};
    144151
     152class SoundTowns_EuphonyTrackQueue {
     153public:
     154        SoundTowns_EuphonyTrackQueue::SoundTowns_EuphonyTrackQueue
     155                (SoundTowns_EuphonyDriver * driver, SoundTowns_EuphonyTrackQueue * last);
     156        SoundTowns_EuphonyTrackQueue::~SoundTowns_EuphonyTrackQueue() {}
     157
     158        void release();
     159        void initDriver();
     160        void loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop = 0);
     161        void loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop = 0);
     162        void setPlayBackStatus(bool playing);
     163        SoundTowns_EuphonyTrackQueue * reset();
     164        bool isPlaying() {return _playing; }
     165        uint8 * trackData() {return _trackData; }
     166
     167        bool _loop;
     168        SoundTowns_EuphonyTrackQueue * _next;
     169
     170private:
     171        uint8 * _trackData;
     172        uint8 * _used;
     173        uint8 * _fchan;
     174        uint8 * _wchan;
     175        bool _playing;
     176        SoundTowns_EuphonyDriver * _driver;
     177        SoundTowns_EuphonyTrackQueue * _last;
     178};
     179
    145180class MidiParser_EuD : public MidiParser {
    146181public:
    147         MidiParser_EuD();
    148 
    149         bool loadMusic (byte *data, uint32 unused = 0);
     182        MidiParser_EuD(SoundTowns_EuphonyTrackQueue * queue);
     183        bool loadMusic (byte *data, uint32 size);
    150184        int32 calculateTempo(int16 val);
    151185
    152186protected:
    153187        void parseNextEvent (EventInfo &info);
    154188        void resetTracking();
     189        void setup();
    155190
    156191        byte * _enable;
    157192        byte * _mode;
     
    159194        byte * _adjVelo;
    160195        int8 * _adjNote;
    161196
    162         byte _tempo[3];
    163 
    164197        uint8 _firstBaseTickStep;
    165198        uint8 _nextBaseTickStep;
    166199        uint32 _initialTempo;
    167200        uint32 _baseTick;
     201
     202        byte _tempo[3];
     203        SoundTowns_EuphonyTrackQueue * _queue;
    168204};
    169205
    170 class FMT_EuphonyDriver : public MidiDriver_Emulated {
     206class SoundTowns_EuphonyDriver : public MidiDriver_Emulated {
    171207public:
    172         FMT_EuphonyDriver(Audio::Mixer *mixer);
    173         virtual ~FMT_EuphonyDriver();
     208        SoundTowns_EuphonyDriver(Audio::Mixer *mixer);
     209        virtual ~SoundTowns_EuphonyDriver();
    174210
    175211        int open();
    176212        void close();
     
    179215        uint32 property(int prop, uint32 param) { return 0; }
    180216
    181217        void setPitchBendRange(byte channel, uint range) { }
    182         //void sysEx(const byte *msg, uint16 length);
    183218        void loadFmInstruments(const byte *instr);
    184219        void loadWaveInstruments(const byte *instr);
    185220
     221        SoundTowns_EuphonyTrackQueue * queue() { return _queue; }
     222
    186223        MidiChannel *allocateChannel() { return 0; }
    187224        MidiChannel *getPercussionChannel() { return 0; }
    188225
     
    190227        void assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber);
    191228        void removeChannel(uint8 midiChannelNumber);
    192229
     230        void setVolume(int val = -1) { if (val >= 0) _volume = val; }
     231        int getVolume(int val = -1) { return _volume; }
     232
    193233        // AudioStream API
    194234        bool isStereo() const { return true; }
    195235        int getRate() const { return _mixer->getOutputRate(); }
     
    198238
    199239protected:
    200240        void nextTick(int16 *buf1, int buflen);
    201         int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; }
    202241        void rate(uint16 r);
    203242
    204243        void generateSamples(int16 *buf, int len);
     
    206245        MidiChannel_EuD_FM *_fChannel[6];
    207246        MidiChannel_EuD_WAVE *_wChannel[8];
    208247        MidiChannel_EuD * _channel[16];
     248        SoundTowns_EuphonyTrackQueue * _queue;
    209249
    210250        int _volume;
    211251        bool _fading;
     
    532572        _velocity = velo;
    533573}
    534574
    535 FMT_EuphonyDriver::FMT_EuphonyDriver(Audio::Mixer *mixer)
     575SoundTowns_EuphonyDriver::SoundTowns_EuphonyDriver(Audio::Mixer *mixer)
    536576: MidiDriver_Emulated(mixer) {
    537577
    538578        _volume = 255;
    539         _fadestate = 300;
     579        _fadestate = EUPHONY_FADEOUT_TICKS;
     580        _queue = 0;
    540581
    541582        MidiDriver_YM2612::createLookupTables();
    542583
     
    551592
    552593        rate(getRate());
    553594        fading(0);
     595
     596        _queue = new SoundTowns_EuphonyTrackQueue(this, 0);
    554597}
    555598
    556 FMT_EuphonyDriver::~FMT_EuphonyDriver() {
     599SoundTowns_EuphonyDriver::~SoundTowns_EuphonyDriver() {
    557600        for (int i = 0; i < 6; i++)
    558601                delete _fChannel[i];
    559602        for (int i = 0; i < 8; i++)
     
    577620                        _waveSounds[i] = 0;
    578621                }
    579622        }
     623
     624        if (_queue) {
     625                _queue->release();
     626                delete _queue;
     627                _queue = 0;
     628        }
    580629}
    581630
    582 int FMT_EuphonyDriver::open() {
     631int SoundTowns_EuphonyDriver::open() {
    583632        if (_isOpen)
    584633                return MERR_ALREADY_OPEN;
    585 
    586634        MidiDriver_Emulated::open();
    587635
    588636        _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle,
    589637                this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
     638
    590639        return 0;
    591640}
    592641
    593 void FMT_EuphonyDriver::close() {
     642void SoundTowns_EuphonyDriver::close() {
    594643        if (!_isOpen)
    595644                return;
    596645        _isOpen = false;
    597646        _mixer->stopHandle(_mixerSoundHandle);
    598647}
    599648
    600 void FMT_EuphonyDriver::send(uint32 b) {
     649void SoundTowns_EuphonyDriver::send(uint32 b) {
    601650        send(b & 0xF, b & 0xFFFFFFF0);
    602651}
    603652
    604 void FMT_EuphonyDriver::send(byte chan, uint32 b) {
    605         //byte param3 = (byte) ((b >> 24) & 0xFF);
    606 
     653void SoundTowns_EuphonyDriver::send(byte chan, uint32 b) {
    607654        byte param2 = (byte) ((b >> 16) & 0xFF);
    608655        byte param1 = (byte) ((b >>  8) & 0xFF);
    609656        byte cmd    = (byte) (b & 0xF0);
     
    662709                        _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000);
    663710                break;
    664711        default:
    665                 warning("FMT_EuphonyDriver: Unknown send() command 0x%02X", cmd);
     712                warning("SoundTowns_EuphonyDriver: Unknown send() command 0x%02X", cmd);
    666713        }
    667714}
    668715
    669 void FMT_EuphonyDriver::loadFmInstruments(const byte *instr) {
     716void SoundTowns_EuphonyDriver::loadFmInstruments(const byte *instr) {
    670717        if (_fmInstruments)
    671718                delete [] _fmInstruments;
    672719        _fmInstruments = new uint8[0x1800];
    673720        memcpy(_fmInstruments, instr, 0x1800);
    674721}
    675722
    676 void FMT_EuphonyDriver::loadWaveInstruments(const byte *instr) {
     723void SoundTowns_EuphonyDriver::loadWaveInstruments(const byte *instr) {
    677724        if (_waveInstruments)
    678725                delete [] _waveInstruments;
    679726        _waveInstruments = new uint8[0x1000];
     
    698745}
    699746
    700747
    701 void FMT_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) {
     748void SoundTowns_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) {
    702749        _channel[midiChannelNumber] = _fChannel[fmChannelNumber];
    703750}
    704751
    705 void FMT_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) {
     752void SoundTowns_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) {
    706753        _channel[midiChannelNumber] = _wChannel[waveChannelNumber];
    707754}
    708755
    709 void FMT_EuphonyDriver::removeChannel(uint8 midiChannelNumber) {
     756void SoundTowns_EuphonyDriver::removeChannel(uint8 midiChannelNumber) {
    710757        _channel[midiChannelNumber] = 0;
    711758}
    712759
    713 void FMT_EuphonyDriver::generateSamples(int16 *data, int len) {
     760void SoundTowns_EuphonyDriver::generateSamples(int16 *data, int len) {
    714761        memset(data, 0, 2 * sizeof(int16) * len);
    715762        nextTick(data, len);
    716763}
    717764
    718 void FMT_EuphonyDriver::nextTick(int16 *buf1, int buflen) {
     765void SoundTowns_EuphonyDriver::nextTick(int16 *buf1, int buflen) {
    719766        int32 *buf0 = (int32 *)buf1;
    720767
    721768        for (int i = 0; i < ARRAYSIZE(_channel); i++) {
     
    724771        }
    725772
    726773        for (int i = 0; i < buflen; ++i) {
    727                 int s = int( float(buf0[i] * volume()) * float((float)_fadestate / 300) );
     774                int s = int( float(buf0[i] * _volume) * float((float)_fadestate / EUPHONY_FADEOUT_TICKS) );
    728775                buf1[i*2] = buf1[i*2+1] = (s >> 9) & 0xffff;
    729776        }
    730777
    731778        if (_fading) {
    732                 if (_fadestate)
     779                if (_fadestate) {
    733780                        _fadestate--;
    734                 else
     781                } else {
    735782                        _fading = false;
     783                        _queue->setPlayBackStatus(false);
     784                }
    736785        }
    737786}
    738787
    739 void FMT_EuphonyDriver::rate(uint16 r) {
     788void SoundTowns_EuphonyDriver::rate(uint16 r) {
    740789        for (uint8 i = 0; i < 16; i++) {
    741790                if (_channel[i])
    742791                        _channel[i]->rate(r);
    743792        }
    744793}
    745794
    746 void FMT_EuphonyDriver::fading(bool status) {
     795void SoundTowns_EuphonyDriver::fading(bool status) {
    747796        _fading = status;
    748797        if (!_fading)
    749                 _fadestate = 300;
     798                _fadestate = EUPHONY_FADEOUT_TICKS;
    750799}
    751800
    752 MidiParser_EuD::MidiParser_EuD() : MidiParser(),
     801MidiParser_EuD::MidiParser_EuD(SoundTowns_EuphonyTrackQueue * queue) : MidiParser(),
    753802        _firstBaseTickStep(0x33), _nextBaseTickStep(0x33) {
    754803                _initialTempo = calculateTempo(0x5a);
     804                _queue = queue;
    755805}
    756806
    757807void MidiParser_EuD::parseNextEvent(EventInfo &info) {
    758808        byte *pos = _position._play_pos;
    759809
     810        if (_queue->_next) {
     811                if (info.ext.type == 0x2F) {
     812                        unloadMusic();
     813                        memset(&info, 0, sizeof(EventInfo));
     814                        pos = _position._play_pos = _tracks[0] = _queue->trackData() + 0x806;
     815                } else if (_active_track == 255) {
     816                        _queue = _queue->_next;
     817                        setup();
     818                        setTrack(0);
     819                        _queue->setPlayBackStatus(true);
     820                        return;
     821                } else if (!_queue->isPlaying()) {
     822                        unloadMusic();
     823                        _queue = _queue->_next;
     824                        setup();
     825                        setTrack(0);
     826                        _queue->setPlayBackStatus(true);
     827                        return;
     828                }
     829        }
     830
    760831        while (true) {
    761832                byte cmd = *pos;
    762833                byte evt = (cmd & 0xF0);
     
    830901                        break;
    831902                } else if (cmd == 0xFD || cmd == 0xFE) {
    832903                        // End of track.
    833                         if (_autoLoop)
     904                        if (_autoLoop) {
     905                                unloadMusic();
     906                                _queue->setPlayBackStatus(true);
    834907                                pos = info.start = _tracks[0];
    835                         else
     908                        } else {
    836909                                info.start = pos;
     910                        }
    837911
    838912                        uint32 last = _position._last_event_tick;
    839913                        uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick;
     
    852926        _position._play_pos = pos;
    853927}
    854928
    855 bool MidiParser_EuD::loadMusic(byte *data, uint32) {
    856         unloadMusic();
     929bool MidiParser_EuD::loadMusic(byte *data, uint32 size) {
     930        bool loop = _autoLoop;
    857931
    858         _enable = data + 0x354;
    859         _mode = data + 0x374;
    860         _channel = data + 0x394;
    861         _adjVelo = data + 0x3B4;
    862         _adjNote = (int8*) data + 0x3D4;
    863 
    864         _firstBaseTickStep = data[0x804];
    865         _initialTempo = calculateTempo((data[0x805] > 0xfc) ? 0x5a : data[0x805]);
    866 
    867         _num_tracks = 1;
    868         _ppqn = 120;
    869         _tracks[0] = data + 0x806;
    870 
    871         resetTracking();
    872         setTrack (0);
    873 
     932        if (_queue->isPlaying() && !_queue->_loop) {
     933                _queue->loadDataToEndOfQueue(data, size, loop);
     934        } else {
     935                unloadMusic();
     936                _queue = _queue->reset();
     937                _queue->release();
     938                _queue->loadDataToCurrentPosition(data, size, loop);
     939                setup();
     940                setTrack(0);
     941                _queue->setPlayBackStatus(true);
     942        }
    874943        return true;
    875944}
    876945
     
    892961
    893962void MidiParser_EuD::resetTracking() {
    894963        MidiParser::resetTracking();
     964
    895965        _nextBaseTickStep = _firstBaseTickStep;
    896966        _baseTick = 0;
    897967        setTempo(_initialTempo);
     968        _queue->setPlayBackStatus(false);
    898969}
    899970
     971void MidiParser_EuD::setup() {
     972        uint8 *data = _queue->trackData();
     973        if (!data)
     974                return;
     975        _queue->initDriver();
     976
     977        _enable = data + 0x354;
     978        _mode = data + 0x374;
     979        _channel = data + 0x394;
     980        _adjVelo = data + 0x3B4;
     981        _adjNote = (int8*) data + 0x3D4;
     982
     983        _nextBaseTickStep = _firstBaseTickStep = data[0x804];
     984        _initialTempo = calculateTempo((data[0x805] > 0xfc) ? 0x5a : data[0x805]);
     985
     986        property(MidiParser::mpAutoLoop, _queue->_loop);
     987
     988        _num_tracks = 1;
     989        _ppqn = 120;
     990        _tracks[0] = data + 0x806;
     991}
     992
     993SoundTowns_EuphonyTrackQueue::SoundTowns_EuphonyTrackQueue(SoundTowns_EuphonyDriver * driver, SoundTowns_EuphonyTrackQueue * last) {
     994        _trackData = 0;
     995        _next = 0;
     996        _driver = driver;
     997        _last = last;
     998        _used = _fchan = _wchan = 0;
     999        _playing = false;
     1000}
     1001
     1002void SoundTowns_EuphonyTrackQueue::setPlayBackStatus(bool playing) {
     1003        SoundTowns_EuphonyTrackQueue * i = this;
     1004        do {
     1005                i->_playing = playing;
     1006                i = i->_next;
     1007        } while (i);
     1008}
     1009
     1010SoundTowns_EuphonyTrackQueue * SoundTowns_EuphonyTrackQueue::reset() {
     1011        SoundTowns_EuphonyTrackQueue * i = this;
     1012        while (i->_last)
     1013                i = i->_last;
     1014        return i;
     1015}
     1016
     1017void SoundTowns_EuphonyTrackQueue::loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop) {
     1018        if (_trackData)
     1019                delete [] _trackData;
     1020        _trackData = new uint8[0xC58A];
     1021        memset(_trackData, 0, 0xC58A);
     1022        Screen::decodeFrame4(trackdata, _trackData, size);
     1023
     1024        _used = _trackData + 0x374;
     1025        _fchan = _trackData + 0x6d4;
     1026        _wchan = _trackData + 0x6dA;
     1027        _loop = loop;
     1028        _playing = false;
     1029}
     1030
     1031void SoundTowns_EuphonyTrackQueue::loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop) {
     1032        if (!_trackData) {
     1033                loadDataToCurrentPosition(trackdata, size, loop);
     1034                return;
     1035        }
     1036
     1037        SoundTowns_EuphonyTrackQueue * i = this;
     1038        while (i->_next)
     1039                i = i->_next;
     1040
     1041        i = i->_next = new SoundTowns_EuphonyTrackQueue(_driver, i);
     1042        i->_trackData = new uint8[0xC58A];
     1043        memset(i->_trackData, 0, 0xC58A);
     1044        Screen::decodeFrame4(trackdata, i->_trackData, size);
     1045
     1046        i->_used = i->_trackData + 0x374;
     1047        i->_fchan = i->_trackData + 0x6d4;
     1048        i->_wchan = i->_trackData + 0x6dA;
     1049        i->_loop = loop;
     1050        i->_playing = _playing;
     1051}
     1052
     1053void SoundTowns_EuphonyTrackQueue::release() {
     1054        SoundTowns_EuphonyTrackQueue * i = _next;
     1055        _next = 0;
     1056        _playing = false;
     1057        _used = _fchan = _wchan = 0;
     1058
     1059        if (_trackData) {
     1060                delete [] _trackData;
     1061                _trackData = 0;
     1062        }
     1063
     1064        while (i) {
     1065                if (i->_trackData) {
     1066                        delete [] i->_trackData;
     1067                        i->_trackData = 0;
     1068                }
     1069                i = i->_next;
     1070                if (i)
     1071                        delete i->_last;
     1072        }
     1073}
     1074
     1075void SoundTowns_EuphonyTrackQueue::initDriver() {
     1076        for (uint8 i = 0; i < 6; i++) {
     1077                if (_used[_fchan[i]])
     1078                        _driver->assignFmChannel(_fchan[i], i);
     1079        }
     1080
     1081        for (uint8 i = 0; i < 8; i++) {
     1082                if (_used[_wchan[i]])
     1083                        _driver->assignWaveChannel(_wchan[i], i);
     1084        }
     1085
     1086        for (uint8 i = 0; i < 16; i++) {
     1087                if (!_used[i])
     1088                        _driver->removeChannel(i);
     1089        }
     1090        _driver->send(0x79B0);
     1091}
     1092
    9001093SoundTowns::SoundTowns(KyraEngine *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _lastTrack(-1),
    901          _currentSFX(0), _sfxFileData(0), _sfxFileIndex((uint)-1), _sfxWDTable(0), _parser(0), _musicTrackData(0) {
     1094         _currentSFX(0), _sfxFileData(0), _sfxFileIndex((uint)-1), _sfxWDTable(0), _parser(0), _sfxVolume(255) {
    9021095
    903         _driver = new FMT_EuphonyDriver(_mixer);
     1096        _driver = new SoundTowns_EuphonyDriver(_mixer);
    9041097        int ret = open();
    9051098        if (ret != MERR_ALREADY_OPEN && ret != 0) {
    9061099                error("couldn't open midi driver");
     
    9161109        _driver->setTimerCallback(0, 0);
    9171110        close();
    9181111
    919         if (_musicTrackData)
    920                 delete [] _musicTrackData;
    921 
    9221112        _driver = 0;
    9231113}
    9241114
     
    9501140        track -= 2;
    9511141
    9521142        static const CDTrackTable tTable[] = {
    953                 { 0x04000, 1,  0 },
    954                 { 0x05480, 1,  6 },
    955                 { 0x05E70, 0,  1 },
    956                 { 0x06D90, 1,  3 },
    957                 { 0x072C0, 0, -1 },
    958                 { 0x075F0, 1, -1 },
    959                 { 0x07880, 1, -1 },
    960                 { 0x089C0, 0, -1 },
    961                 { 0x09080, 0, -1 },
    962                 { 0x091D0, 1,  4 },
    963                 { 0x0A880, 1,  5 },
    964                 { 0x0AF50, 0, -1 },
    965                 { 0x0B1A0, 1, -1 },
    966                 { 0x0B870, 0, -1 },
    967                 { 0x0BCF0, 1, -1 },
    968                 { 0x0C5D0, 1,  7 },
    969                 { 0x0D3E0, 1,  8 },
    970                 { 0x0e7b0, 1,  2 },
    971                 { 0x0edc0, 0, -1 },
    972                 { 0x0eef0, 1,  9 },
    973                 { 0x10540, 1, 10 },
    974                 { 0x10d80, 0, -1 },
    975                 { 0x10E30, 0, -1 },
    976                 { 0x10FC0, 0, -1 },
    977                 { 0x11310, 1, -1 },
    978                 { 0x11A20, 1, -1 },
    979                 { 0x12380, 0, -1 },
    980                 { 0x12540, 1, -1 },
    981                 { 0x12730, 1, -1 },
    982                 { 0x12A90, 1, 11 },
    983                 { 0x134D0, 0, -1 },
    984                 { 0x00000, 0, -1 },
    985                 { 0x13770, 0, -1 },
    986                 { 0x00000, 0, -1 },
    987                 { 0x00000, 0, -1 },
    988                 { 0x00000, 0, -1 },
    989                 { 0x00000, 0, -1 },
    990                 { 0x14710, 1, 12 },
    991                 { 0x15DF0, 1, 13 },
    992                 { 0x16030, 1, 14 },
    993                 { 0x17030, 0, -1 },
    994                 { 0x17650, 0, -1 },
    995                 { 0x134D0, 0, -1 },
    996                 { 0x178E0, 1, -1 },
    997                 { 0x18200, 0, -1 },
    998                 { 0x18320, 0, -1 },
    999                 { 0x184A0, 0, -1 },
    1000                 { 0x18BB0, 0, -1 },
    1001                 { 0x19040, 0, 19 },
    1002                 { 0x19B50, 0, 20 },
    1003                 { 0x17650, 0, -1 },
    1004                 { 0x1A730, 1, 21 },
    1005                 { 0x00000, 0, -1 },
    1006                 { 0x12380, 0, -1 },
    1007                 { 0x1B810, 0, -1 },
    1008                 { 0x1BA50, 0, 15 },
    1009                 { 0x1C190, 0, 16 },
    1010                 { 0x1CA50, 0, 17 },
    1011                 { 0x1D100, 0, 18 },
     1143                { 0x04000, 1,  0 },     { 0x05480, 1,  6 },     { 0x05E70, 0,  1 },
     1144                { 0x06D90, 1,  3 },     { 0x072C0, 0, -1 },     { 0x075F0, 1, -1 },
     1145                { 0x07880, 1, -1 },     { 0x089C0, 0, -1 },     { 0x09080, 0, -1 },
     1146                { 0x091D0, 1,  4 },     { 0x0A880, 1,  5 },     { 0x0AF50, 0, -1 },
     1147                { 0x0B1A0, 1, -1 },     { 0x0B870, 0, -1 },     { 0x0BCF0, 1, -1 },
     1148                { 0x0C5D0, 1,  7 },     { 0x0D3E0, 1,  8 },     { 0x0e7b0, 1,  2 },
     1149                { 0x0edc0, 0, -1 },     { 0x0eef0, 1,  9 },     { 0x10540, 1, 10 },
     1150                { 0x10d80, 0, -1 },     { 0x10E30, 0, -1 },     { 0x10FC0, 0, -1 },
     1151                { 0x11310, 1, -1 },     { 0x11A20, 1, -1 },     { 0x12380, 0, -1 },
     1152                { 0x12540, 1, -1 },     { 0x12730, 1, -1 },     { 0x12A90, 1, 11 },
     1153                { 0x134D0, 0, -1 },     { 0x00000, 0, -1 },     { 0x13770, 0, -1 },
     1154                { 0x00000, 0, -1 },     { 0x00000, 0, -1 },     { 0x00000, 0, -1 },
     1155                { 0x00000, 0, -1 },     { 0x14710, 1, 12 },     { 0x15DF0, 1, 13 },
     1156                { 0x16030, 1, 14 },     { 0x17030, 0, -1 },     { 0x17650, 0, -1 },
     1157                { 0x134D0, 0, -1 },     { 0x178E0, 1, -1 },     { 0x18200, 0, -1 },
     1158                { 0x18320, 0, -1 },     { 0x184A0, 0, -1 },     { 0x18BB0, 0, -1 },
     1159                { 0x19040, 0, 19 },     { 0x19B50, 0, 20 },     { 0x17650, 0, -1 },
     1160                { 0x1A730, 1, 21 },     { 0x00000, 0, -1 },     { 0x12380, 0, -1 },
     1161                { 0x1B810, 0, -1 },     { 0x1BA50, 0, 15 },     { 0x1C190, 0, 16 },
     1162                { 0x1CA50, 0, 17 },     { 0x1D100, 0, 18 }
    10121163        };
    10131164
    10141165        int trackNum = tTable[track].track;
     
    10171168        if (track == _lastTrack && _musicEnabled)
    10181169                return;
    10191170
    1020         haltTrack();
     1171        beginFadeOut();
    10211172
    10221173        if (_musicEnabled == 2 && trackNum != -1) {
    10231174                AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0);
     
    10351186        AudioCD.updateCD();
    10361187        if (_parser) {
    10371188                Common::StackLock lock(_mutex);
    1038 
    10391189                _parser->setTrack(0);
    10401190                _parser->jumpToTick(0);
    1041 
    10421191                _parser->unloadMusic();
    10431192                delete _parser;
    10441193                _parser = 0;
    1045 
    10461194                setVolume(255);
    10471195        }
     1196        _driver->queue()->release();
    10481197}
    10491198
     1199void SoundTowns::setMusicVolume(int volume) {
     1200        _driver->setVolume(volume);
     1201}
     1202
    10501203void SoundTowns::loadSoundFile(uint file) {
    10511204        if (_sfxFileIndex == file)
    10521205                return;
     
    11431296
    11441297        _currentSFX = Audio::makeLinearInputStream(sfxPlaybackBuffer, playbackBufferSize,
    11451298                outputRate, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
    1146         _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX);
     1299        _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX, -1, _sfxVolume);
    11471300}
    11481301
    11491302void SoundTowns::beginFadeOut() {
     
    11811334}
    11821335
    11831336bool SoundTowns::loadInstruments() {
    1184         if (!_musicTrackData)
    1185                 _musicTrackData = new uint8[0xC58A];
    1186 
    1187         memset(_musicTrackData, 0, 0xC58A);
    11881337        uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0);
    11891338        if (!twm)
    11901339                return false;
    1191         Screen::decodeFrame4(twm, _musicTrackData, 0x8BF0);
    1192         _driver->loadFmInstruments(_musicTrackData + 8);
     1340        _driver->queue()->loadDataToCurrentPosition(twm, 0x8BF0);
     1341        _driver->loadFmInstruments(_driver->queue()->trackData() + 8);
    11931342
    1194         memset (_musicTrackData, 0, 0xC58A);
    1195         Screen::decodeFrame4(twm + 0x0CA0, _musicTrackData, 0xC58A);
     1343        _driver->queue()->loadDataToCurrentPosition(twm + 0x0CA0, 0xC58A);
     1344        _driver->loadWaveInstruments(_driver->queue()->trackData() + 8);
    11961345        delete [] twm;
    1197         _driver->loadWaveInstruments(_musicTrackData + 8);
     1346        _driver->queue()->release();
    11981347
    11991348        return true;
    12001349}
    12011350
    12021351void SoundTowns::playEuphonyTrack(uint32 offset, int loop) {
    1203         if (!_musicTrackData)
    1204                 _musicTrackData = new uint8[0xC58A];
    1205 
    1206         memset(_musicTrackData, 0, 0xC58A);
    12071352        uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0);
    1208         Screen::decodeFrame4(twm + 0x4b70 + offset, _musicTrackData, 0xC58A);
    1209         delete [] twm;
    12101353
    1211         Common::StackLock lock(_mutex);
    1212 
    1213         uint8 * used = _musicTrackData + 0x374;
    1214         uint8 * fchan = _musicTrackData + 0x6d4;
    1215         uint8 * wchan = _musicTrackData + 0x6dA;
    1216 
    1217         for (uint8 i = 0; i < 6; i++) {
    1218                 if (used[fchan[i]])
    1219                         _driver->assignFmChannel(fchan[i], i);
     1354        if (!_parser) {
     1355                _parser = new MidiParser_EuD(_driver->queue());
     1356                _parser->setMidiDriver(this);
     1357                _parser->setTimerRate(getBaseTempo());
    12201358        }
    12211359
    1222         for (uint8 i = 0; i < 8; i++) {
    1223                 if (used[wchan[i]])
    1224                         _driver->assignWaveChannel(wchan[i], i);
    1225         }
    1226 
    1227         for (uint8 i = 0; i < 16; i++) {
    1228                 if (!used[i])
    1229                         _driver->removeChannel(i);
    1230         }
    1231         _driver->send(0x79B0);
    1232 
    1233         if (_parser)
    1234                 delete _parser;
    1235 
    1236         _parser = new MidiParser_EuD;
    12371360        _parser->property(MidiParser::mpAutoLoop, loop);
    1238         _parser->loadMusic(_musicTrackData, 0);
    1239         _parser->jumpToTick(0);
     1361        _parser->loadMusic(twm + 0x4b70 + offset, 0xC58A);
    12401362
    1241         _parser->setMidiDriver(this);
    1242         _parser->setTimerRate(getBaseTempo());
     1363        delete [] twm;
    12431364}
    12441365
    12451366void SoundTowns::onTimer(void * data) {
     
    13021423        0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01
    13031424};
    13041425
     1426//      KYRA 2
     1427
     1428SoundTowns_v2::SoundTowns_v2(KyraEngine *vm, Audio::Mixer *mixer) :
     1429         Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), /*_driver(0),*/
     1430         _twnTrackData(0), _sfxVolume(255) {
     1431}
     1432
     1433SoundTowns_v2::~SoundTowns_v2() {
     1434        /*if (_driver)
     1435                delete _driver;*/
     1436        if (_twnTrackData)
     1437                delete [] _twnTrackData;
     1438}
     1439
     1440bool SoundTowns_v2::init() {
     1441        //_driver = new SoundTowns_v2_TwnDriver(_mixer);
     1442        _vm->checkCD();
     1443        Common::File f;
     1444        if (_musicEnabled && (f.exists("track1.mp3") ||
     1445                f.exists("track1.ogg") || f.exists("track1.flac")  || f.exists("track1.fla")))
     1446                        _musicEnabled = 2;
     1447        return true;//_driver->init();
     1448}
     1449
     1450void SoundTowns_v2::process() {
     1451        AudioCD.updateCD();
     1452}
     1453
     1454void SoundTowns_v2::setMusicVolume(int volume) {
     1455        /* TODO */
     1456}
     1457
     1458void SoundTowns_v2::playTrack(uint8 track) {
     1459        if (track == _lastTrack && _musicEnabled)
     1460                return;
     1461
     1462        int trackNum = -1;
     1463        for (int i = 0; i < _themes[_currentTheme].cdaTableSize; i++) {
     1464                if (track == _themes[_currentTheme].cdaTable[i * 2]) {
     1465                        trackNum = _themes[_currentTheme].cdaTable[i * 2 + 1] - 1;
     1466                        break;
     1467                }
     1468        }
     1469
     1470        haltTrack();
     1471
     1472        // TODO: figure out when to loop and when not for CD Audio
     1473        bool loop = false;
     1474
     1475        if (_musicEnabled == 2 && trackNum != -1) {
     1476                AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0);
     1477                AudioCD.updateCD();
     1478        } else if (_musicEnabled) {
     1479                char musicfile[13];
     1480                sprintf(musicfile, "%s%d.twn", _themes[_currentTheme].twnFilename, track);
     1481                if (_twnTrackData)
     1482                        delete [] _twnTrackData;
     1483                _twnTrackData = _vm->resource()->fileData(musicfile, 0);
     1484                //_driver->loadData(_twnTrackData);
     1485        }
     1486
     1487        _lastTrack = track;
     1488}
     1489
     1490void SoundTowns_v2::haltTrack() {
     1491        _lastTrack = -1;
     1492        AudioCD.stop();
     1493        AudioCD.updateCD();
     1494        //_driver->reset();
     1495}
     1496
     1497void SoundTowns_v2::voicePlay(const char *file) {
     1498        static const uint16 rates[] =   { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 };
     1499
     1500        uint8 * data = _vm->resource()->fileData(file, 0);
     1501        uint8 * src = data;
     1502
     1503        uint16 sfxRate = rates[READ_LE_UINT16(src)];
     1504        src += 2;
     1505        bool compressed = (READ_LE_UINT16(src) & 1) ? true : false;
     1506        src += 2;
     1507        uint32 outsize = READ_LE_UINT32(src);
     1508        uint8 *sfx = (uint8*) malloc(outsize);
     1509        uint8 *dst = sfx;
     1510        src += 4;
     1511
     1512        if (compressed) {
     1513                for (uint32 i = outsize; i;) {
     1514                        uint8 cnt = *src++;
     1515                        if (cnt & 0x80) {
     1516                                cnt &= 0x7F;
     1517                                memset(dst, *src++, cnt);
     1518                        } else {
     1519                                memcpy(dst, src, cnt);
     1520                                src += cnt;
     1521                        }
     1522                        dst += cnt;
     1523                        i -= cnt;
     1524                }
     1525        } else {
     1526                memcpy(dst, src, outsize);
     1527        }
     1528
     1529        for (uint32 i = 0; i < outsize; i++) {
     1530                uint8 cmd = sfx[i];
     1531                if (cmd & 0x80) {
     1532                        cmd = ~cmd;
     1533                } else {
     1534                        cmd |= 0x80;
     1535                        if (cmd == 0xff)
     1536                                cmd--;
     1537                }
     1538                if (cmd < 0x80)
     1539                        cmd = 0x80 - cmd;
     1540                sfx[i] = cmd;
     1541        }
     1542
     1543        uint32 outputRate = uint32(11025 * SoundTowns::semitoneAndSampleRate_to_sampleStep(0x3c, 0x3c, sfxRate, 11025, 0x2000));
     1544
     1545        _currentSFX = Audio::makeLinearInputStream(sfx, outsize, outputRate,
     1546                Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
     1547        _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX, -1, _sfxVolume);
     1548
     1549        delete [] data;
     1550}
     1551
     1552void SoundTowns_v2::beginFadeOut() {
     1553        //_driver->fadeOut();
     1554        haltTrack();
     1555}
     1556
     1557const uint8 SoundTowns_v2::_cdaTrackTableK2Intro[] =    {
     1558        0x03, 0x01, 0x04, 0x02, 0x05, 0x03, 0x06, 0x04, 0x07, 0x05, 0x08, 0x06
     1559};
     1560
     1561const uint8 SoundTowns_v2::_cdaTrackTableK2Ingame[] =   {
     1562        0x02, 0x07, 0x03, 0x08, 0x04, 0x09, 0x07, 0x0A, 0x0C, 0x0B, 0x0D, 0x0C, 0x0E, 0x0D, 0x0F, 0x0E,
     1563        0x10, 0x0F, 0x12, 0x10, 0x13, 0x11, 0x15, 0x12, 0x17, 0x13, 0x18, 0x14, 0x19, 0x15, 0x1A, 0x16,
     1564        0x1B, 0x17, 0x1C, 0x18, 0x1D, 0x19, 0x1E, 0x1A, 0x1F, 0x1B, 0x21, 0x1C, 0x22, 0x1D, 0x23, 0x1E,
     1565        0x24, 0x1F, 0x25, 0x20, 0x26, 0x21, 0x27, 0x22, 0x28, 0x23, 0x29, 0x24, 0x2A, 0x25, 0x2B, 0x26,
     1566        0x2C, 0x27, 0x2D, 0x28, 0x2E, 0x29, 0x2F, 0x2A, 0x30, 0x2B, 0x31, 0x2C, 0x32, 0x2D, 0x33, 0x2E,
     1567        0x34, 0x2F, 0x35, 0x30, 0x36, 0x31, 0x37, 0x32, 0x38, 0x33, 0x39, 0x34, 0x3A, 0x35, 0x3B, 0x36,
     1568        0x3C, 0x37, 0x3D, 0x38, 0x3E, 0x39, 0x3F, 0x3A, 0x40, 0x3B, 0x41, 0x3C, 0x42, 0x3D, 0x43, 0x3E,
     1569        0x44, 0x3F, 0x45, 0x40, 0x46, 0x41, 0x47, 0x42, 0x48, 0x43, 0x49, 0x44, 0x4A, 0x45, 0x4B, 0x46,
     1570        0x4C, 0x47, 0x4D, 0x48, 0x4E, 0x49, 0x4F, 0x4A, 0x50, 0x4B, 0x51, 0x4C, 0x52, 0x4D, 0x53, 0x4E,
     1571        0x54, 0x4F, 0x55, 0x50, 0x56, 0x51, 0x57, 0x52
     1572};
     1573
     1574const uint8 SoundTowns_v2::_cdaTrackTableK2Finale[] =   {
     1575        0x03, 0x53, 0x04, 0x54
     1576};
     1577
     1578const Kyra2AudioThemes SoundTowns_v2::_themes[] = {
     1579        { _cdaTrackTableK2Intro,        ARRAYSIZE(_cdaTrackTableK2Intro) >> 1,  "intro"         },
     1580        { _cdaTrackTableK2Ingame,       ARRAYSIZE(_cdaTrackTableK2Ingame) >> 1, "k2"            },
     1581        { _cdaTrackTableK2Finale,       ARRAYSIZE(_cdaTrackTableK2Finale) >> 1, "finale"        }
     1582};
     1583
    13051584} // end of namespace Kyra
    13061585
     1586#undef EUPHONY_FADEOUT_TICKS
     1587
     1588#if _MSC_VER >= 1400
     1589#undef  sprintf
     1590#endif
     1591 No newline at end of file