Ticket #8757: kyraSoundTownsEtc_v2.patch

File kyraSoundTownsEtc_v2.patch, 43.4 KB (added by athrxx, 16 years ago)

new version of the same patch

  • 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
     
    440474
    441475REGISTER_PLUGIN(KYRA, "Legend of Kyrandia Engine", "The Legend of Kyrandia (C) Westwood Studios");
    442476
     477
  • 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
     
    232235
    233236} // End of namespace Kyra
    234237
     238
  • kyra_v2.cpp

     
    113113
    114114        KyraEngine::init();
    115115
     116        if (!_sound->init())
     117                error("Couldn't init sound");
     118
    116119        _debugger = new Debugger_v2(this);
    117120        assert(_debugger);
    118121        _text = new TextDisplayer_v2(this, _screen);
     
    145148        }
    146149
    147150        for (int i = 0; i < 33; i++)
    148                 _sequenceStringsDuration[i] = strlen(_sequenceStrings[i]) * 8;
     151                _sequenceStringsDuration[i] = (int) strlen(_sequenceStrings[i]) * 8;
    149152
    150153        // No mouse display in demo
    151154        if (_flags.isDemo)
     
    164167}
    165168
    166169int 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");
     170        if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
     171                seq_showStarcraftLogo();
    171172
    172173        seq_playSequences(kSequenceVirgin, kSequenceZanfaun);
    173174        //seq_playSequences(kSequenceFunters, kSequenceFrash);
     
    175176        if (_menuChoice == 1) {
    176177                // load just the pak files needed for ingame
    177178                _res->unloadAllPakFiles();
    178                 _res->loadFileList("FILEDATA.FDT");
     179                if (_flags.platform == Common::kPlatformPC && (_flags.isTalkie || _flags.isDemo)) {
     180                        _res->loadFileList("FILEDATA.FDT");
     181                } else if (_flags.platform == Common::kPlatformPC) {
     182                        //TODO
     183                } else if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
     184                        char tmpfilename[13];
     185                        static const char * pakfiles [] = { "KYRA.DAT", "AUDIO.PAK", "CAULDRON.PAK",
     186                                "MISC_CPS.PAK", "MISC_EMC.PAK", "OTHER.PAK", "VOC.PAK", "WSCORE.PAK" };
     187                        for (int i = 0; i < 8; i++)
     188                                _res->loadPakFile(pakfiles[i]);
     189                        for (int i = 1; i < 10; i++) {
     190                                sprintf(tmpfilename, "COST%d_SH.PAK", i);
     191                                _res->loadPakFile(tmpfilename);
     192                        }
     193                        for (int i = 1; i < 6; i++) {
     194                                sprintf(tmpfilename, "HOFCH_%d.PAK", i);
     195                                _res->loadPakFile(tmpfilename);
     196                        }
     197                }
     198
    179199                startup();
    180200                runLoop();
    181201                cleanup();
     
    187207}
    188208
    189209void KyraEngine_v2::startup() {
    190         _sound->setSoundFileList(_dosSoundFileList, _dosSoundFileListSize);
     210        snd_assignMusicData(kMusicIngame);
     211        // The track map is exactly the same
     212        // for FM-TOWNS and DOS
    191213        _trackMap = _dosTrackMap;
    192214        _trackMapSize = _dosTrackMapSize;
    193215
     
    306328                //      waitTicks(5);
    307329                //      sub_270A0();
    308330                //}
    309                
     331
    310332                if (_system->getMillis() > _nextIdleAnim)
    311333                        showIdleAnim();
    312334
     
    15401562        _sound->loadSoundFile(file);
    15411563}
    15421564
     1565void KyraEngine_v2::snd_assignMusicData(kMusicDataID id) {
     1566        if (_flags.platform == Common::kPlatformPC) {
     1567                if (id == kMusicIntro)
     1568                        _sound->setSoundFileList(_dosSoundFileListIntro, 1);
     1569                else if (id == kMusicFinale)
     1570                        _sound->setSoundFileList(_dosSoundFileListFinale, 1);
     1571                else
     1572                        _sound->setSoundFileList(_dosSoundFileList, _dosSoundFileListSize);
     1573        } else {
     1574                _sound->assignData(id);
     1575        }
     1576}
     1577
    15431578void KyraEngine_v2::playVoice(int high, int low) {
    15441579        int vocFile = high * 10000 + low * 10;
    15451580        snd_playVoiceFile(vocFile);
     
    16321667                case 48:
    16331668                        snd_playSoundEffect(0x38);
    16341669                        break;
    1635                
     1670
    16361671                default:
    16371672                        break;
    16381673                }
     
    19041939
    19051940} // end of namespace Kyra
    19061941
    1907 
  • kyra_v2.h

     
    7474        kSequenceHand4
    7575};
    7676
     77
    7778class WSAMovieV2;
    7879class KyraEngine_v2;
    7980class TextDisplayer_v2;
     
    143144        uint16 unk1;
    144145};
    145146
     147enum kMusicDataID {
     148        kMusicIntro = 0,
     149        kMusicIngame,
     150        kMusicFinale
     151};
     152
    146153class KyraEngine_v2 : public KyraEngine {
    147154friend class Debugger_v2;
    148155friend class TextDisplayer_v2;
     
    225232        void seq_printCreditsString(uint16 strIndex, int x, int y, uint8 * colorMap, uint8 textcolor);
    226233        void seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width,
    227234                WSAMovieV2 * wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos);
     235        int seq_generateFixedRandomValue(int rangeFirst, int rangeLast);
     236        void seq_showStarcraftLogo();
    228237
    229238        void seq_init();
    230239        void seq_uninit();
     
    246255        static const int8 _dosTrackMap[];
    247256        static const int _dosTrackMapSize;
    248257
    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 
    256258protected:
    257259        // game initialization
    258260        void startup();
     
    628630
    629631        virtual void snd_playVoiceFile(int id);
    630632        void snd_loadSoundFile(int id);
     633        void snd_assignMusicData(kMusicDataID id);
    631634
    632635        void playVoice(int high, int low);
    633636
     
    639642        void timerFunc6(int);
    640643
    641644        void setTimer1DelaySecs(int secs);
    642        
     645
    643646        uint32 _nextIdleAnim;
    644647        int _lastIdleScript;
    645648
     
    846849        static const int _sequenceStringsSize_TOWNS_EN;
    847850        static const char *_sequenceStrings_PC_EN[];
    848851        static const int _sequenceStringsSize_PC_EN;
     852        static const char _actorScreenStrings_PC_EN[];
     853        static const int _actorScreenStringsSize_PC_EN;
    849854
    850855        int _sequenceStringsDuration[33];
    851856
     
    861866        int _seqFrameCounter;
    862867        int _seqWsaCurrentFrame;
    863868        bool _seqSpecialFlag;
     869        int _seqRandomizeBase;
    864870        bool _seqSubframePlaying;
    865871        uint8 _seqTextColor[2];
    866872        uint8 _seqTextColorMap[16];
     
    883889#endif
    884890
    885891
     892
  • 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) ?     kMusicFinale : kMusicIntro);
    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(kMusicIngame);
    15471545        _sound->loadSoundFile(3);
    15481546        _sound->playTrack(3);
    15491547
     
    15521550
    15531551        // TODO
    15541552
    1555         _sound->setSoundFileList(_dosSoundFileListFinale, 1);
     1553        snd_assignMusicData(kMusicFinale);
    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 {
     2223                _res->loadPakFile("INTROVOC.PAK");
     2224                if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
     2225                        _res->loadPakFile("WSCORE.PAK");
     2226        }
    21612227}
    21622228
    21632229void KyraEngine_v2::seq_uninit() {
     
    21812247void KyraEngine_v2::seq_makeBookOrCauldronAppear(int type) {
    21822248        _screen->hideMouse();
    21832249        showMessage(0, 0xCF);
    2184        
     2250
    21852251        if (type == 1) {
    21862252                seq_makeBookAppear();
    21872253        } else if (type == 2) {
     
    21902256
    21912257        _screen->copyRegionToBuffer(2, 0, 0, 320, 200, _screenBuffer);
    21922258        _screen->loadBitmap("_PLAYALL.CPS", 3, 3, 0);
    2193        
     2259
    21942260        static int16 bookCauldronRects[] = {
    21952261                0x46, 0x90, 0x7F, 0x2B, // unknown rect (maybe unused?)
    21962262                0xCE, 0x90, 0x2C, 0x2C, // book rect
     
    22152281
    22162282void KyraEngine_v2::seq_makeBookAppear() {
    22172283        _screen->hideMouse();
    2218        
     2284
    22192285        displayInvWsaLastFrame();
    2220        
     2286
    22212287        showMessage(0, 0xCF);
    22222288
    22232289        loadInvWsa("BOOK2.WSA", 0, 4, 2, -1, -1, 0);
    2224        
     2290
    22252291        uint8 *rect = new uint8[_screen->getRectSize(_invWsa.w, _invWsa.h)];
    22262292        assert(rect);
    2227        
     2293
    22282294        _screen->copyRegionToBuffer(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect);
    22292295
    22302296        _invWsa.running = false;
     
    22362302
    22372303        while (true) {
    22382304                _invWsa.timer = _system->getMillis() + _invWsa.delay * _tickLength;
    2239                
     2305
    22402306                _screen->copyBlockToPage(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect);
    22412307
    22422308                _invWsa.wsa->displayFrame(_invWsa.curFrame, 0x4000, 0, 0);
    22432309
    22442310                if (_invWsa.page)
    22452311                        _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, _invWsa.page, 0, Screen::CR_NO_P_CHECK);
    2246                
     2312
    22472313                ++_invWsa.curFrame;
    22482314
    22492315                if (_invWsa.curFrame >= _invWsa.lastFrame && !_quitFlag)
    22502316                        break;
    2251                
     2317
    22522318                switch (_invWsa.curFrame) {
    22532319                case 39:
    22542320                        snd_playSoundEffect(0xCA);
     
    23842450
    23852451} // end of namespace Kyra
    23862452
     2453
  • sound.h

     
    5252#include "sound/softsynth/ym2612.h"
    5353
    5454#include "kyra/kyra.h"
     55#include "kyra/kyra_v2.h"
    5556
    5657namespace Audio {
    5758class AudioStream;
     
    5960
    6061namespace Kyra {
    6162
    62 /** 
     63/**
    6364 * Analog audio output device API for Kyrandia games.
    6465 * It countains functionallity to play music tracks,
    6566 * sound effects and voices.
     
    109110        virtual void setSoundFileList(const char * const *list, uint s) { _soundFileList = list; _soundFileListSize = s; }
    110111
    111112        /**
     113         * Selects preset bundles of music files
     114         * and cd audio tracks the output device will use
     115         * when playing a track and/or sound effect.
     116         *
     117         * @param id    kMusicIntro, kMusicIngame or kMusicFinale
     118         */     
     119        virtual void assignData(kMusicDataID id) { _currentTheme = id; }
     120
     121        /**
    112122         * Load a specifc sound file for use of
    113123         * playing music and sound effects.
    114124         */
     
    161171         *
    162172         * @param file  file to be played
    163173         */
    164         void voicePlay(const char *file);
     174        virtual void voicePlay(const char *file);
    165175
    166176        /**
    167177         * Checks if a voice is being played.
     
    180190        int _musicEnabled;
    181191        bool _sfxEnabled;
    182192
     193        int _currentTheme;
     194
    183195        KyraEngine *_vm;
    184196        Audio::Mixer *_mixer;
    185197
     
    213225 * Dune II, Kyrandia 1 and 2. While Dune II and
    214226 * Kyrandia 1 are using exact the same format, the
    215227 * one of Kyrandia 2 slightly differs.
    216  * 
     228 *
    217229 * See AdlibDriver for more information.
    218230 * @see AdlibDriver
    219231 */
     
    268280 *
    269281 * Currently it does not initialize the MT-32 output properly,
    270282 * so MT-32 output does sound a bit odd in some cases.
    271  * 
     283 *
    272284 * TODO: this code needs some serious cleanup and rework
    273285 * to support MT-32 and GM properly.
    274286 */
     
    341353        Common::Mutex _mutex;
    342354};
    343355
    344 class FMT_EuphonyDriver;
     356class SoundTowns_EuphonyDriver;
    345357class SoundTowns : public MidiDriver, public Sound {
    346358public:
    347359        SoundTowns(KyraEngine *vm, Audio::Mixer *mixer);
     
    350362        bool init();
    351363        void process();
    352364
    353         void setVolume(int) { /* TODO */ }
    354         int getVolume() { return 255; /* TODO */ }
     365        void setVolume(int) {}
     366        int getVolume() { return 255; }
    355367
     368        void setMusicVolume(int volume);
     369        void setSoundEffectsVolume(int volume) { _sfxVolume = (uint8) volume; }
     370
    356371        void loadSoundFile(uint file);
    357372
    358373        void playTrack(uint8 track);
     
    387402        Audio::AudioStream *_currentSFX;
    388403        Audio::SoundHandle _sfxHandle;
    389404
    390         int _currentTrackTable;
    391405        uint _sfxFileIndex;
    392406        uint8 *_sfxFileData;
     407        uint8 _sfxVolume;
    393408
    394         FMT_EuphonyDriver * _driver;
     409        SoundTowns_EuphonyDriver * _driver;
    395410        MidiParser * _parser;
    396         uint8 *_musicTrackData;
    397411
    398412        Common::Mutex _mutex;
    399413
    400         static const char *_sfxFiles[];
    401         static const int _sfxFilenum;
    402414        static const uint8 _sfxBTTable[256];
    403415        const uint8 *_sfxWDTable;
    404416};
    405417
     418//class SoundTowns_v2_TwnDriver;
     419class SoundTowns_v2: public Sound {
     420public:
     421        SoundTowns_v2(KyraEngine *vm, Audio::Mixer *mixer);
     422        ~SoundTowns_v2();
     423
     424        bool init();
     425        void process();
     426
     427        void setVolume(int) {}
     428        int getVolume() { return 255; }
     429
     430        void setMusicVolume(int volume);
     431        void setSoundEffectsVolume(int volume) { _sfxVolume = (uint8) volume; }
     432
     433        void loadSoundFile(uint file) {}
     434
     435        void playTrack(uint8 track);
     436        void haltTrack();
     437        void beginFadeOut();
     438
     439        void voicePlay(const char *file);
     440        void playSoundEffect(uint8) {}
     441
     442private:
     443        int _lastTrack;
     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
     456        static const struct Kyra2AudioThemes {
     457                const uint8 * cdaTable;
     458                const uint8 cdaTableSize;
     459                const char * twnFilename;
     460        } _themes[];
     461};
     462
    406463class MixedSoundDriver : public Sound {
    407464public:
    408465        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
    3637#include <math.h>
    3738
     39#define         EUPHONY_FADEOUT_TICKS           600
     40
    3841namespace Kyra {
    3942
    40 enum EuD_ChannelState { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing };
     43enum ChannelState { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing };
    4144
    4245class MidiChannel_EuD : public MidiChannel {
    4346public:
     
    125128                        const int8 *_samples;
    126129                } * _snd[8];
    127130                struct Env {
    128                         EuD_ChannelState state;
     131                        ChannelState state;
    129132                        int32 currentLevel;
    130133                        int32 rate;
    131134                        int32 tickCount;
     
    142145        } * _voice;
    143146};
    144147
     148class SoundTowns_EuphonyTrackQueue {
     149public:
     150        SoundTowns_EuphonyTrackQueue::SoundTowns_EuphonyTrackQueue
     151                (SoundTowns_EuphonyDriver * driver, SoundTowns_EuphonyTrackQueue * last);
     152        SoundTowns_EuphonyTrackQueue::~SoundTowns_EuphonyTrackQueue() {}
     153
     154        void release();
     155        void initDriver();
     156        void loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop = 0);
     157        void loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop = 0);
     158        void setPlayBackStatus(bool playing);
     159        SoundTowns_EuphonyTrackQueue * reset();
     160        bool isPlaying() {return _playing; }
     161        uint8 * trackData() {return _trackData; }
     162
     163        bool _loop;
     164        SoundTowns_EuphonyTrackQueue * _next;
     165
     166private:
     167        uint8 * _trackData;
     168        uint8 * _used;
     169        uint8 * _fchan;
     170        uint8 * _wchan;
     171        bool _playing;
     172        SoundTowns_EuphonyDriver * _driver;
     173        SoundTowns_EuphonyTrackQueue * _last;
     174};
     175
    145176class MidiParser_EuD : public MidiParser {
    146177public:
    147         MidiParser_EuD();
    148 
    149         bool loadMusic (byte *data, uint32 unused = 0);
     178        MidiParser_EuD(SoundTowns_EuphonyTrackQueue * queue);
     179        bool loadMusic (byte *data, uint32 size);
    150180        int32 calculateTempo(int16 val);
    151181
    152182protected:
    153183        void parseNextEvent (EventInfo &info);
    154184        void resetTracking();
     185        void setup();
    155186
    156187        byte * _enable;
    157188        byte * _mode;
     
    159190        byte * _adjVelo;
    160191        int8 * _adjNote;
    161192
    162         byte _tempo[3];
    163 
    164193        uint8 _firstBaseTickStep;
    165194        uint8 _nextBaseTickStep;
    166195        uint32 _initialTempo;
    167196        uint32 _baseTick;
     197
     198        byte _tempo[3];
     199        SoundTowns_EuphonyTrackQueue * _queue;
    168200};
    169201
    170 class FMT_EuphonyDriver : public MidiDriver_Emulated {
     202class SoundTowns_EuphonyDriver : public MidiDriver_Emulated {
    171203public:
    172         FMT_EuphonyDriver(Audio::Mixer *mixer);
    173         virtual ~FMT_EuphonyDriver();
     204        SoundTowns_EuphonyDriver(Audio::Mixer *mixer);
     205        virtual ~SoundTowns_EuphonyDriver();
    174206
    175207        int open();
    176208        void close();
     
    179211        uint32 property(int prop, uint32 param) { return 0; }
    180212
    181213        void setPitchBendRange(byte channel, uint range) { }
    182         //void sysEx(const byte *msg, uint16 length);
    183214        void loadFmInstruments(const byte *instr);
    184215        void loadWaveInstruments(const byte *instr);
    185216
     217        SoundTowns_EuphonyTrackQueue * queue() { return _queue; }
     218
    186219        MidiChannel *allocateChannel() { return 0; }
    187220        MidiChannel *getPercussionChannel() { return 0; }
    188221
     
    190223        void assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber);
    191224        void removeChannel(uint8 midiChannelNumber);
    192225
     226        void setVolume(int val = -1) { if (val >= 0) _volume = val; }
     227        int getVolume(int val = -1) { return _volume; }
     228
    193229        // AudioStream API
    194230        bool isStereo() const { return true; }
    195231        int getRate() const { return _mixer->getOutputRate(); }
     
    198234
    199235protected:
    200236        void nextTick(int16 *buf1, int buflen);
    201         int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; }
    202237        void rate(uint16 r);
    203238
    204239        void generateSamples(int16 *buf, int len);
     
    206241        MidiChannel_EuD_FM *_fChannel[6];
    207242        MidiChannel_EuD_WAVE *_wChannel[8];
    208243        MidiChannel_EuD * _channel[16];
     244        SoundTowns_EuphonyTrackQueue * _queue;
    209245
    210246        int _volume;
    211247        bool _fading;
     
    532568        _velocity = velo;
    533569}
    534570
    535 FMT_EuphonyDriver::FMT_EuphonyDriver(Audio::Mixer *mixer)
     571SoundTowns_EuphonyDriver::SoundTowns_EuphonyDriver(Audio::Mixer *mixer)
    536572: MidiDriver_Emulated(mixer) {
    537573
    538574        _volume = 255;
    539         _fadestate = 300;
     575        _fadestate = EUPHONY_FADEOUT_TICKS;
     576        _queue = 0;
    540577
    541578        MidiDriver_YM2612::createLookupTables();
    542579
     
    551588
    552589        rate(getRate());
    553590        fading(0);
     591
     592        _queue = new SoundTowns_EuphonyTrackQueue(this, 0);
    554593}
    555594
    556 FMT_EuphonyDriver::~FMT_EuphonyDriver() {
     595SoundTowns_EuphonyDriver::~SoundTowns_EuphonyDriver() {
    557596        for (int i = 0; i < 6; i++)
    558597                delete _fChannel[i];
    559598        for (int i = 0; i < 8; i++)
     
    577616                        _waveSounds[i] = 0;
    578617                }
    579618        }
     619
     620        if (_queue) {
     621                _queue->release();
     622                delete _queue;
     623                _queue = 0;
     624        }
    580625}
    581626
    582 int FMT_EuphonyDriver::open() {
     627int SoundTowns_EuphonyDriver::open() {
    583628        if (_isOpen)
    584629                return MERR_ALREADY_OPEN;
    585 
    586630        MidiDriver_Emulated::open();
    587631
    588632        _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle,
    589633                this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
     634
    590635        return 0;
    591636}
    592637
    593 void FMT_EuphonyDriver::close() {
     638void SoundTowns_EuphonyDriver::close() {
    594639        if (!_isOpen)
    595640                return;
    596641        _isOpen = false;
    597642        _mixer->stopHandle(_mixerSoundHandle);
    598643}
    599644
    600 void FMT_EuphonyDriver::send(uint32 b) {
     645void SoundTowns_EuphonyDriver::send(uint32 b) {
    601646        send(b & 0xF, b & 0xFFFFFFF0);
    602647}
    603648
    604 void FMT_EuphonyDriver::send(byte chan, uint32 b) {
    605         //byte param3 = (byte) ((b >> 24) & 0xFF);
    606 
     649void SoundTowns_EuphonyDriver::send(byte chan, uint32 b) {
    607650        byte param2 = (byte) ((b >> 16) & 0xFF);
    608651        byte param1 = (byte) ((b >>  8) & 0xFF);
    609652        byte cmd    = (byte) (b & 0xF0);
     
    662705                        _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000);
    663706                break;
    664707        default:
    665                 warning("FMT_EuphonyDriver: Unknown send() command 0x%02X", cmd);
     708                warning("SoundTowns_EuphonyDriver: Unknown send() command 0x%02X", cmd);
    666709        }
    667710}
    668711
    669 void FMT_EuphonyDriver::loadFmInstruments(const byte *instr) {
     712void SoundTowns_EuphonyDriver::loadFmInstruments(const byte *instr) {
    670713        if (_fmInstruments)
    671714                delete [] _fmInstruments;
    672715        _fmInstruments = new uint8[0x1800];
    673716        memcpy(_fmInstruments, instr, 0x1800);
    674717}
    675718
    676 void FMT_EuphonyDriver::loadWaveInstruments(const byte *instr) {
     719void SoundTowns_EuphonyDriver::loadWaveInstruments(const byte *instr) {
    677720        if (_waveInstruments)
    678721                delete [] _waveInstruments;
    679722        _waveInstruments = new uint8[0x1000];
     
    698741}
    699742
    700743
    701 void FMT_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) {
     744void SoundTowns_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) {
    702745        _channel[midiChannelNumber] = _fChannel[fmChannelNumber];
    703746}
    704747
    705 void FMT_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) {
     748void SoundTowns_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) {
    706749        _channel[midiChannelNumber] = _wChannel[waveChannelNumber];
    707750}
    708751
    709 void FMT_EuphonyDriver::removeChannel(uint8 midiChannelNumber) {
     752void SoundTowns_EuphonyDriver::removeChannel(uint8 midiChannelNumber) {
    710753        _channel[midiChannelNumber] = 0;
    711754}
    712755
    713 void FMT_EuphonyDriver::generateSamples(int16 *data, int len) {
     756void SoundTowns_EuphonyDriver::generateSamples(int16 *data, int len) {
    714757        memset(data, 0, 2 * sizeof(int16) * len);
    715758        nextTick(data, len);
    716759}
    717760
    718 void FMT_EuphonyDriver::nextTick(int16 *buf1, int buflen) {
     761void SoundTowns_EuphonyDriver::nextTick(int16 *buf1, int buflen) {
    719762        int32 *buf0 = (int32 *)buf1;
    720763
    721764        for (int i = 0; i < ARRAYSIZE(_channel); i++) {
     
    724767        }
    725768
    726769        for (int i = 0; i < buflen; ++i) {
    727                 int s = int( float(buf0[i] * volume()) * float((float)_fadestate / 300) );
     770                int s = int( float(buf0[i] * _volume) * float((float)_fadestate / EUPHONY_FADEOUT_TICKS) );
    728771                buf1[i*2] = buf1[i*2+1] = (s >> 9) & 0xffff;
    729772        }
    730773
    731774        if (_fading) {
    732                 if (_fadestate)
     775                if (_fadestate) {
    733776                        _fadestate--;
    734                 else
     777                } else {
    735778                        _fading = false;
     779                        _queue->setPlayBackStatus(false);
     780                }
    736781        }
    737782}
    738783
    739 void FMT_EuphonyDriver::rate(uint16 r) {
     784void SoundTowns_EuphonyDriver::rate(uint16 r) {
    740785        for (uint8 i = 0; i < 16; i++) {
    741786                if (_channel[i])
    742787                        _channel[i]->rate(r);
    743788        }
    744789}
    745790
    746 void FMT_EuphonyDriver::fading(bool status) {
     791void SoundTowns_EuphonyDriver::fading(bool status) {
    747792        _fading = status;
    748793        if (!_fading)
    749                 _fadestate = 300;
     794                _fadestate = EUPHONY_FADEOUT_TICKS;
    750795}
    751796
    752 MidiParser_EuD::MidiParser_EuD() : MidiParser(),
     797MidiParser_EuD::MidiParser_EuD(SoundTowns_EuphonyTrackQueue * queue) : MidiParser(),
    753798        _firstBaseTickStep(0x33), _nextBaseTickStep(0x33) {
    754799                _initialTempo = calculateTempo(0x5a);
     800                _queue = queue;
    755801}
    756802
    757803void MidiParser_EuD::parseNextEvent(EventInfo &info) {
    758804        byte *pos = _position._play_pos;
    759805
     806        if (_queue->_next) {
     807                if (info.ext.type == 0x2F) {
     808                        unloadMusic();
     809                        memset(&info, 0, sizeof(EventInfo));
     810                        pos = _position._play_pos = _tracks[0] = _queue->trackData() + 0x806;
     811                } else if (_active_track == 255) {
     812                        _queue = _queue->_next;
     813                        setup();
     814                        setTrack(0);
     815                        _queue->setPlayBackStatus(true);
     816                        return;
     817                } else if (!_queue->isPlaying()) {
     818                        unloadMusic();
     819                        _queue = _queue->_next;
     820                        setup();
     821                        setTrack(0);
     822                        _queue->setPlayBackStatus(true);
     823                        return;
     824                }
     825        }
     826
    760827        while (true) {
    761828                byte cmd = *pos;
    762829                byte evt = (cmd & 0xF0);
     
    830897                        break;
    831898                } else if (cmd == 0xFD || cmd == 0xFE) {
    832899                        // End of track.
    833                         if (_autoLoop)
     900                        if (_autoLoop) {
     901                                unloadMusic();
     902                                _queue->setPlayBackStatus(true);
    834903                                pos = info.start = _tracks[0];
    835                         else
     904                        } else {
    836905                                info.start = pos;
     906                        }
    837907
    838908                        uint32 last = _position._last_event_tick;
    839909                        uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick;
     
    852922        _position._play_pos = pos;
    853923}
    854924
    855 bool MidiParser_EuD::loadMusic(byte *data, uint32) {
    856         unloadMusic();
     925bool MidiParser_EuD::loadMusic(byte *data, uint32 size) {
     926        bool loop = _autoLoop;
    857927
    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 
     928        if (_queue->isPlaying() && !_queue->_loop) {
     929                _queue->loadDataToEndOfQueue(data, size, loop);
     930        } else {
     931                unloadMusic();
     932                _queue = _queue->reset();
     933                _queue->release();
     934                _queue->loadDataToCurrentPosition(data, size, loop);
     935                setup();
     936                setTrack(0);
     937                _queue->setPlayBackStatus(true);
     938        }
    874939        return true;
    875940}
    876941
     
    892957
    893958void MidiParser_EuD::resetTracking() {
    894959        MidiParser::resetTracking();
     960
    895961        _nextBaseTickStep = _firstBaseTickStep;
    896962        _baseTick = 0;
    897963        setTempo(_initialTempo);
     964        _queue->setPlayBackStatus(false);
    898965}
    899966
     967void MidiParser_EuD::setup() {
     968        uint8 *data = _queue->trackData();
     969        if (!data)
     970                return;
     971        _queue->initDriver();
     972
     973        _enable = data + 0x354;
     974        _mode = data + 0x374;
     975        _channel = data + 0x394;
     976        _adjVelo = data + 0x3B4;
     977        _adjNote = (int8*) data + 0x3D4;
     978
     979        _nextBaseTickStep = _firstBaseTickStep = data[0x804];
     980        _initialTempo = calculateTempo((data[0x805] > 0xfc) ? 0x5a : data[0x805]);
     981
     982        property(MidiParser::mpAutoLoop, _queue->_loop);
     983
     984        _num_tracks = 1;
     985        _ppqn = 120;
     986        _tracks[0] = data + 0x806;
     987}
     988
     989SoundTowns_EuphonyTrackQueue::SoundTowns_EuphonyTrackQueue(SoundTowns_EuphonyDriver * driver, SoundTowns_EuphonyTrackQueue * last) {
     990        _trackData = 0;
     991        _next = 0;
     992        _driver = driver;
     993        _last = last;
     994        _used = _fchan = _wchan = 0;
     995        _playing = false;
     996}
     997
     998void SoundTowns_EuphonyTrackQueue::setPlayBackStatus(bool playing) {
     999        SoundTowns_EuphonyTrackQueue * i = this;
     1000        do {
     1001                i->_playing = playing;
     1002                i = i->_next;
     1003        } while (i);
     1004}
     1005
     1006SoundTowns_EuphonyTrackQueue * SoundTowns_EuphonyTrackQueue::reset() {
     1007        SoundTowns_EuphonyTrackQueue * i = this;
     1008        while (i->_last)
     1009                i = i->_last;
     1010        return i;
     1011}
     1012
     1013void SoundTowns_EuphonyTrackQueue::loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop) {
     1014        if (_trackData)
     1015                delete [] _trackData;
     1016        _trackData = new uint8[0xC58A];
     1017        memset(_trackData, 0, 0xC58A);
     1018        Screen::decodeFrame4(trackdata, _trackData, size);
     1019
     1020        _used = _trackData + 0x374;
     1021        _fchan = _trackData + 0x6d4;
     1022        _wchan = _trackData + 0x6dA;
     1023        _loop = loop;
     1024        _playing = false;
     1025}
     1026
     1027void SoundTowns_EuphonyTrackQueue::loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop) {
     1028        if (!_trackData) {
     1029                loadDataToCurrentPosition(trackdata, size, loop);
     1030                return;
     1031        }
     1032
     1033        SoundTowns_EuphonyTrackQueue * i = this;
     1034        while (i->_next)
     1035                i = i->_next;
     1036
     1037        i = i->_next = new SoundTowns_EuphonyTrackQueue(_driver, i);
     1038        i->_trackData = new uint8[0xC58A];
     1039        memset(i->_trackData, 0, 0xC58A);
     1040        Screen::decodeFrame4(trackdata, i->_trackData, size);
     1041
     1042        i->_used = i->_trackData + 0x374;
     1043        i->_fchan = i->_trackData + 0x6d4;
     1044        i->_wchan = i->_trackData + 0x6dA;
     1045        i->_loop = loop;
     1046        i->_playing = _playing;
     1047}
     1048
     1049void SoundTowns_EuphonyTrackQueue::release() {
     1050        SoundTowns_EuphonyTrackQueue * i = _next;
     1051        _next = 0;
     1052        _playing = false;
     1053        _used = _fchan = _wchan = 0;
     1054
     1055        if (_trackData) {
     1056                delete [] _trackData;
     1057                _trackData = 0;
     1058        }
     1059
     1060        while (i) {
     1061                if (i->_trackData) {
     1062                        delete [] i->_trackData;
     1063                        i->_trackData = 0;
     1064                }
     1065                i = i->_next;
     1066                if (i)
     1067                        delete i->_last;
     1068        }
     1069}
     1070
     1071void SoundTowns_EuphonyTrackQueue::initDriver() {
     1072        for (uint8 i = 0; i < 6; i++) {
     1073                if (_used[_fchan[i]])
     1074                        _driver->assignFmChannel(_fchan[i], i);
     1075        }
     1076
     1077        for (uint8 i = 0; i < 8; i++) {
     1078                if (_used[_wchan[i]])
     1079                        _driver->assignWaveChannel(_wchan[i], i);
     1080        }
     1081
     1082        for (uint8 i = 0; i < 16; i++) {
     1083                if (!_used[i])
     1084                        _driver->removeChannel(i);
     1085        }
     1086        _driver->send(0x79B0);
     1087}
     1088
    9001089SoundTowns::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) {
     1090         _currentSFX(0), _sfxFileData(0), _sfxFileIndex((uint)-1), _sfxWDTable(0), _parser(0), _sfxVolume(255) {
    9021091
    903         _driver = new FMT_EuphonyDriver(_mixer);
     1092        _driver = new SoundTowns_EuphonyDriver(_mixer);
    9041093        int ret = open();
    9051094        if (ret != MERR_ALREADY_OPEN && ret != 0) {
    9061095                error("couldn't open midi driver");
     
    9161105        _driver->setTimerCallback(0, 0);
    9171106        close();
    9181107
    919         if (_musicTrackData)
    920                 delete [] _musicTrackData;
    921 
    9221108        _driver = 0;
    9231109}
    9241110
     
    9501136        track -= 2;
    9511137
    9521138        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 },
     1139                { 0x04000, 1,  0 },     { 0x05480, 1,  6 },     { 0x05E70, 0,  1 },
     1140                { 0x06D90, 1,  3 },     { 0x072C0, 0, -1 },     { 0x075F0, 1, -1 },
     1141                { 0x07880, 1, -1 },     { 0x089C0, 0, -1 },     { 0x09080, 0, -1 },
     1142                { 0x091D0, 1,  4 },     { 0x0A880, 1,  5 },     { 0x0AF50, 0, -1 },
     1143                { 0x0B1A0, 1, -1 },     { 0x0B870, 0, -1 },     { 0x0BCF0, 1, -1 },
     1144                { 0x0C5D0, 1,  7 },     { 0x0D3E0, 1,  8 },     { 0x0e7b0, 1,  2 },
     1145                { 0x0edc0, 0, -1 },     { 0x0eef0, 1,  9 },     { 0x10540, 1, 10 },
     1146                { 0x10d80, 0, -1 },     { 0x10E30, 0, -1 },     { 0x10FC0, 0, -1 },
     1147                { 0x11310, 1, -1 },     { 0x11A20, 1, -1 },     { 0x12380, 0, -1 },
     1148                { 0x12540, 1, -1 },     { 0x12730, 1, -1 },     { 0x12A90, 1, 11 },
     1149                { 0x134D0, 0, -1 },     { 0x00000, 0, -1 },     { 0x13770, 0, -1 },
     1150                { 0x00000, 0, -1 },     { 0x00000, 0, -1 },     { 0x00000, 0, -1 },
     1151                { 0x00000, 0, -1 },     { 0x14710, 1, 12 },     { 0x15DF0, 1, 13 },
     1152                { 0x16030, 1, 14 },     { 0x17030, 0, -1 },     { 0x17650, 0, -1 },
     1153                { 0x134D0, 0, -1 },     { 0x178E0, 1, -1 },     { 0x18200, 0, -1 },
     1154                { 0x18320, 0, -1 },     { 0x184A0, 0, -1 },     { 0x18BB0, 0, -1 },
     1155                { 0x19040, 0, 19 },     { 0x19B50, 0, 20 },     { 0x17650, 0, -1 },
     1156                { 0x1A730, 1, 21 },     { 0x00000, 0, -1 },     { 0x12380, 0, -1 },
     1157                { 0x1B810, 0, -1 },     { 0x1BA50, 0, 15 },     { 0x1C190, 0, 16 },
     1158                { 0x1CA50, 0, 17 },     { 0x1D100, 0, 18 }
    10121159        };
    10131160
    10141161        int trackNum = tTable[track].track;
     
    10171164        if (track == _lastTrack && _musicEnabled)
    10181165                return;
    10191166
    1020         haltTrack();
     1167        beginFadeOut();
    10211168
    10221169        if (_musicEnabled == 2 && trackNum != -1) {
    10231170                AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0);
     
    10351182        AudioCD.updateCD();
    10361183        if (_parser) {
    10371184                Common::StackLock lock(_mutex);
    1038 
    10391185                _parser->setTrack(0);
    10401186                _parser->jumpToTick(0);
    1041 
    10421187                _parser->unloadMusic();
    10431188                delete _parser;
    10441189                _parser = 0;
    1045 
    10461190                setVolume(255);
    10471191        }
     1192        _driver->queue()->release();
    10481193}
    10491194
     1195void SoundTowns::setMusicVolume(int volume) {
     1196        _driver->setVolume(volume);
     1197}
     1198
    10501199void SoundTowns::loadSoundFile(uint file) {
    10511200        if (_sfxFileIndex == file)
    10521201                return;
     
    11431292
    11441293        _currentSFX = Audio::makeLinearInputStream(sfxPlaybackBuffer, playbackBufferSize,
    11451294                outputRate, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
    1146         _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX);
     1295        _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX, -1, _sfxVolume);
    11471296}
    11481297
    11491298void SoundTowns::beginFadeOut() {
     
    11811330}
    11821331
    11831332bool SoundTowns::loadInstruments() {
    1184         if (!_musicTrackData)
    1185                 _musicTrackData = new uint8[0xC58A];
    1186 
    1187         memset(_musicTrackData, 0, 0xC58A);
    11881333        uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0);
    11891334        if (!twm)
    11901335                return false;
    1191         Screen::decodeFrame4(twm, _musicTrackData, 0x8BF0);
    1192         _driver->loadFmInstruments(_musicTrackData + 8);
     1336        _driver->queue()->loadDataToCurrentPosition(twm, 0x8BF0);
     1337        _driver->loadFmInstruments(_driver->queue()->trackData() + 8);
    11931338
    1194         memset (_musicTrackData, 0, 0xC58A);
    1195         Screen::decodeFrame4(twm + 0x0CA0, _musicTrackData, 0xC58A);
     1339        _driver->queue()->loadDataToCurrentPosition(twm + 0x0CA0, 0xC58A);
     1340        _driver->loadWaveInstruments(_driver->queue()->trackData() + 8);
    11961341        delete [] twm;
    1197         _driver->loadWaveInstruments(_musicTrackData + 8);
     1342        _driver->queue()->release();
    11981343
    11991344        return true;
    12001345}
    12011346
    12021347void SoundTowns::playEuphonyTrack(uint32 offset, int loop) {
    1203         if (!_musicTrackData)
    1204                 _musicTrackData = new uint8[0xC58A];
    1205 
    1206         memset(_musicTrackData, 0, 0xC58A);
    12071348        uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0);
    1208         Screen::decodeFrame4(twm + 0x4b70 + offset, _musicTrackData, 0xC58A);
    1209         delete [] twm;
    12101349
    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);
     1350        if (!_parser) {
     1351                _parser = new MidiParser_EuD(_driver->queue());
     1352                _parser->setMidiDriver(this);
     1353                _parser->setTimerRate(getBaseTempo());
    12201354        }
    12211355
    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;
    12371356        _parser->property(MidiParser::mpAutoLoop, loop);
    1238         _parser->loadMusic(_musicTrackData, 0);
    1239         _parser->jumpToTick(0);
     1357        _parser->loadMusic(twm + 0x4b70 + offset, 0xC58A);
    12401358
    1241         _parser->setMidiDriver(this);
    1242         _parser->setTimerRate(getBaseTempo());
     1359        delete [] twm;
    12431360}
    12441361
    12451362void SoundTowns::onTimer(void * data) {
     
    13021419        0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01
    13031420};
    13041421
     1422//      KYRA 2
     1423
     1424SoundTowns_v2::SoundTowns_v2(KyraEngine *vm, Audio::Mixer *mixer) :
     1425         Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), /*_driver(0),*/
     1426         _twnTrackData(0), _sfxVolume(255) {
     1427}
     1428
     1429SoundTowns_v2::~SoundTowns_v2() {
     1430        /*if (_driver)
     1431                delete _driver;*/
     1432        if (_twnTrackData)
     1433                delete [] _twnTrackData;
     1434}
     1435
     1436bool SoundTowns_v2::init() {
     1437        //_driver = new SoundTowns_v2_TwnDriver(_mixer);
     1438        _vm->checkCD();
     1439        Common::File f;
     1440        if (_musicEnabled && (f.exists("track1.mp3") ||
     1441                f.exists("track1.ogg") || f.exists("track1.flac")  || f.exists("track1.fla")))
     1442                        _musicEnabled = 2;
     1443        return true;//_driver->init();
     1444}
     1445
     1446void SoundTowns_v2::process() {
     1447        AudioCD.updateCD();
     1448}
     1449
     1450void SoundTowns_v2::setMusicVolume(int volume) {
     1451        /* TODO */
     1452}
     1453
     1454void SoundTowns_v2::playTrack(uint8 track) {
     1455        if (track == _lastTrack && _musicEnabled)
     1456                return;
     1457
     1458        int trackNum = -1;
     1459        for (int i = 0; i < _themes[_currentTheme].cdaTableSize; i++) {
     1460                if (track == _themes[_currentTheme].cdaTable[i * 2]) {
     1461                        trackNum = _themes[_currentTheme].cdaTable[i * 2 + 1] - 1;
     1462                        break;
     1463                }
     1464        }
     1465
     1466        haltTrack();
     1467
     1468        // TODO: figure out when to loop and when not for CD Audio
     1469        bool loop = false;
     1470
     1471        if (_musicEnabled == 2 && trackNum != -1) {
     1472                AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0);
     1473                AudioCD.updateCD();
     1474        } else if (_musicEnabled) {
     1475                char musicfile[13];
     1476                sprintf(musicfile, "%s%d.twn", _themes[_currentTheme].twnFilename, track);
     1477                if (_twnTrackData)
     1478                        delete [] _twnTrackData;
     1479                _twnTrackData = _vm->resource()->fileData(musicfile, 0);
     1480                //_driver->loadData(_twnTrackData);
     1481        }
     1482
     1483        _lastTrack = track;
     1484}
     1485
     1486void SoundTowns_v2::haltTrack() {
     1487        _lastTrack = -1;
     1488        AudioCD.stop();
     1489        AudioCD.updateCD();
     1490        //_driver->reset();
     1491}
     1492
     1493void SoundTowns_v2::voicePlay(const char *file) {
     1494        static const uint16 rates[] =   { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 };
     1495
     1496        uint8 * data = _vm->resource()->fileData(file, 0);
     1497        uint8 * src = data;
     1498
     1499        uint16 sfxRate = rates[READ_LE_UINT16(src)];
     1500        src += 2;
     1501        bool compressed = (READ_LE_UINT16(src) & 1) ? true : false;
     1502        src += 2;
     1503        uint32 outsize = READ_LE_UINT32(src);
     1504        uint8 *sfx = (uint8*) malloc(outsize);
     1505        uint8 *dst = sfx;
     1506        src += 4;
     1507
     1508        if (compressed) {
     1509                for (uint32 i = outsize; i;) {
     1510                        uint8 cnt = *src++;
     1511                        if (cnt & 0x80) {
     1512                                cnt &= 0x7F;
     1513                                memset(dst, *src++, cnt);
     1514                        } else {
     1515                                memcpy(dst, src, cnt);
     1516                                src += cnt;
     1517                        }
     1518                        dst += cnt;
     1519                        i -= cnt;
     1520                }
     1521        } else {
     1522                memcpy(dst, src, outsize);
     1523        }
     1524
     1525        for (uint32 i = 0; i < outsize; i++) {
     1526                uint8 cmd = sfx[i];
     1527                if (cmd & 0x80) {
     1528                        cmd = ~cmd;
     1529                } else {
     1530                        cmd |= 0x80;
     1531                        if (cmd == 0xff)
     1532                                cmd--;
     1533                }
     1534                if (cmd < 0x80)
     1535                        cmd = 0x80 - cmd;
     1536                sfx[i] = cmd;
     1537        }
     1538
     1539        uint32 outputRate = uint32(11025 * SoundTowns::semitoneAndSampleRate_to_sampleStep(0x3c, 0x3c, sfxRate, 11025, 0x2000));
     1540
     1541        _currentSFX = Audio::makeLinearInputStream(sfx, outsize, outputRate,
     1542                Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
     1543        _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX, -1, _sfxVolume);
     1544
     1545        delete [] data;
     1546}
     1547
     1548void SoundTowns_v2::beginFadeOut() {
     1549        //_driver->fadeOut();
     1550        haltTrack();
     1551}
     1552
     1553const uint8 SoundTowns_v2::_cdaTrackTableK2Intro[] =    {
     1554        0x03, 0x01, 0x04, 0x02, 0x05, 0x03, 0x06, 0x04, 0x07, 0x05, 0x08, 0x06
     1555};
     1556
     1557const uint8 SoundTowns_v2::_cdaTrackTableK2Ingame[] =   {
     1558        0x02, 0x07, 0x03, 0x08, 0x04, 0x09, 0x07, 0x0A, 0x0C, 0x0B, 0x0D, 0x0C, 0x0E, 0x0D, 0x0F, 0x0E,
     1559        0x10, 0x0F, 0x12, 0x10, 0x13, 0x11, 0x15, 0x12, 0x17, 0x13, 0x18, 0x14, 0x19, 0x15, 0x1A, 0x16,
     1560        0x1B, 0x17, 0x1C, 0x18, 0x1D, 0x19, 0x1E, 0x1A, 0x1F, 0x1B, 0x21, 0x1C, 0x22, 0x1D, 0x23, 0x1E,
     1561        0x24, 0x1F, 0x25, 0x20, 0x26, 0x21, 0x27, 0x22, 0x28, 0x23, 0x29, 0x24, 0x2A, 0x25, 0x2B, 0x26,
     1562        0x2C, 0x27, 0x2D, 0x28, 0x2E, 0x29, 0x2F, 0x2A, 0x30, 0x2B, 0x31, 0x2C, 0x32, 0x2D, 0x33, 0x2E,
     1563        0x34, 0x2F, 0x35, 0x30, 0x36, 0x31, 0x37, 0x32, 0x38, 0x33, 0x39, 0x34, 0x3A, 0x35, 0x3B, 0x36,
     1564        0x3C, 0x37, 0x3D, 0x38, 0x3E, 0x39, 0x3F, 0x3A, 0x40, 0x3B, 0x41, 0x3C, 0x42, 0x3D, 0x43, 0x3E,
     1565        0x44, 0x3F, 0x45, 0x40, 0x46, 0x41, 0x47, 0x42, 0x48, 0x43, 0x49, 0x44, 0x4A, 0x45, 0x4B, 0x46,
     1566        0x4C, 0x47, 0x4D, 0x48, 0x4E, 0x49, 0x4F, 0x4A, 0x50, 0x4B, 0x51, 0x4C, 0x52, 0x4D, 0x53, 0x4E,
     1567        0x54, 0x4F, 0x55, 0x50, 0x56, 0x51, 0x57, 0x52
     1568};
     1569
     1570const uint8 SoundTowns_v2::_cdaTrackTableK2Finale[] =   {
     1571        0x03, 0x53, 0x04, 0x54
     1572};
     1573
     1574const SoundTowns_v2::Kyra2AudioThemes SoundTowns_v2::_themes[] = {
     1575        { _cdaTrackTableK2Intro,        ARRAYSIZE(_cdaTrackTableK2Intro) >> 1,  "intro"         },
     1576        { _cdaTrackTableK2Ingame,       ARRAYSIZE(_cdaTrackTableK2Ingame) >> 1, "k2"            },
     1577        { _cdaTrackTableK2Finale,       ARRAYSIZE(_cdaTrackTableK2Finale) >> 1, "finale"        }
     1578};
     1579
    13051580} // end of namespace Kyra
    13061581
     1582#undef EUPHONY_FADEOUT_TICKS
     1583