Ticket #8757: kyraSoundTownsEtc_v2.patch
File kyraSoundTownsEtc_v2.patch, 43.4 KB (added by , 17 years ago) |
---|
-
detection.cpp
51 51 52 52 #define KYRA2_CD_FLAGS FLAGS(false, false, true, false, Kyra::GI_KYRA2) 53 53 #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) 54 56 55 57 #define KYRA3_CD_FLAGS FLAGS(false, false, true, false, Kyra::GI_KYRA3) 56 58 … … 176 178 { 177 179 "kyra1", 178 180 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 }, 180 186 Common::EN_ANY, 181 187 Common::kPlatformFMTowns, 182 188 Common::ADGF_NO_FLAGS … … 187 193 { 188 194 "kyra1", 189 195 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 }, 191 201 Common::JA_JPN, 192 202 Common::kPlatformFMTowns, 193 203 Common::ADGF_NO_FLAGS … … 332 342 333 343 { 334 344 { 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 { 335 369 "kyra3", 336 370 0, 337 371 AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"), … … 402 436 bool res = true; 403 437 404 438 Kyra::GameFlags flags = gd->flags; 405 439 406 440 flags.lang = gd->desc.language; 407 441 flags.platform = gd->desc.platform; 408 442 … … 440 474 441 475 REGISTER_PLUGIN(KYRA, "Legend of Kyrandia Engine", "The Legend of Kyrandia (C) Westwood Studios"); 442 476 477 -
kyra.cpp
94 94 95 95 if (_flags.platform == Common::kPlatformFMTowns) { 96 96 // 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); 98 101 } else if (_flags.platform == Common::kPlatformPC98) { 99 102 // TODO: currently we don't support the PC98 sound data, 100 103 // but since it has the FM-Towns data files, we just use the … … 232 235 233 236 } // End of namespace Kyra 234 237 238 -
kyra_v2.cpp
113 113 114 114 KyraEngine::init(); 115 115 116 if (!_sound->init()) 117 error("Couldn't init sound"); 118 116 119 _debugger = new Debugger_v2(this); 117 120 assert(_debugger); 118 121 _text = new TextDisplayer_v2(this, _screen); … … 145 148 } 146 149 147 150 for (int i = 0; i < 33; i++) 148 _sequenceStringsDuration[i] = strlen(_sequenceStrings[i]) * 8;151 _sequenceStringsDuration[i] = (int) strlen(_sequenceStrings[i]) * 8; 149 152 150 153 // No mouse display in demo 151 154 if (_flags.isDemo) … … 164 167 } 165 168 166 169 int 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(); 171 172 172 173 seq_playSequences(kSequenceVirgin, kSequenceZanfaun); 173 174 //seq_playSequences(kSequenceFunters, kSequenceFrash); … … 175 176 if (_menuChoice == 1) { 176 177 // load just the pak files needed for ingame 177 178 _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 179 199 startup(); 180 200 runLoop(); 181 201 cleanup(); … … 187 207 } 188 208 189 209 void 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 191 213 _trackMap = _dosTrackMap; 192 214 _trackMapSize = _dosTrackMapSize; 193 215 … … 306 328 // waitTicks(5); 307 329 // sub_270A0(); 308 330 //} 309 331 310 332 if (_system->getMillis() > _nextIdleAnim) 311 333 showIdleAnim(); 312 334 … … 1540 1562 _sound->loadSoundFile(file); 1541 1563 } 1542 1564 1565 void 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 1543 1578 void KyraEngine_v2::playVoice(int high, int low) { 1544 1579 int vocFile = high * 10000 + low * 10; 1545 1580 snd_playVoiceFile(vocFile); … … 1632 1667 case 48: 1633 1668 snd_playSoundEffect(0x38); 1634 1669 break; 1635 1670 1636 1671 default: 1637 1672 break; 1638 1673 } … … 1904 1939 1905 1940 } // end of namespace Kyra 1906 1941 1907 -
kyra_v2.h
74 74 kSequenceHand4 75 75 }; 76 76 77 77 78 class WSAMovieV2; 78 79 class KyraEngine_v2; 79 80 class TextDisplayer_v2; … … 143 144 uint16 unk1; 144 145 }; 145 146 147 enum kMusicDataID { 148 kMusicIntro = 0, 149 kMusicIngame, 150 kMusicFinale 151 }; 152 146 153 class KyraEngine_v2 : public KyraEngine { 147 154 friend class Debugger_v2; 148 155 friend class TextDisplayer_v2; … … 225 232 void seq_printCreditsString(uint16 strIndex, int x, int y, uint8 * colorMap, uint8 textcolor); 226 233 void seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, 227 234 WSAMovieV2 * wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos); 235 int seq_generateFixedRandomValue(int rangeFirst, int rangeLast); 236 void seq_showStarcraftLogo(); 228 237 229 238 void seq_init(); 230 239 void seq_uninit(); … … 246 255 static const int8 _dosTrackMap[]; 247 256 static const int _dosTrackMapSize; 248 257 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 256 258 protected: 257 259 // game initialization 258 260 void startup(); … … 628 630 629 631 virtual void snd_playVoiceFile(int id); 630 632 void snd_loadSoundFile(int id); 633 void snd_assignMusicData(kMusicDataID id); 631 634 632 635 void playVoice(int high, int low); 633 636 … … 639 642 void timerFunc6(int); 640 643 641 644 void setTimer1DelaySecs(int secs); 642 645 643 646 uint32 _nextIdleAnim; 644 647 int _lastIdleScript; 645 648 … … 846 849 static const int _sequenceStringsSize_TOWNS_EN; 847 850 static const char *_sequenceStrings_PC_EN[]; 848 851 static const int _sequenceStringsSize_PC_EN; 852 static const char _actorScreenStrings_PC_EN[]; 853 static const int _actorScreenStringsSize_PC_EN; 849 854 850 855 int _sequenceStringsDuration[33]; 851 856 … … 861 866 int _seqFrameCounter; 862 867 int _seqWsaCurrentFrame; 863 868 bool _seqSpecialFlag; 869 int _seqRandomizeBase; 864 870 bool _seqSubframePlaying; 865 871 uint8 _seqTextColor[2]; 866 872 uint8 _seqTextColorMap[16]; … … 883 889 #endif 884 890 885 891 892 -
sequences_v2.cpp
53 53 }; 54 54 _sound->setSoundFileList(soundFileList, 2); 55 55 } else { 56 const char *const *soundFileList = 57 (startSeq > kSequenceZanfaun) ? _dosSoundFileListFinale : _dosSoundFileListIntro; 58 _sound->setSoundFileList(soundFileList, 1); 56 snd_assignMusicData((startSeq > kSequenceZanfaun) ? kMusicFinale : kMusicIntro); 59 57 } 60 58 _sound->loadSoundFile(0); 61 59 … … 1445 1443 } 1446 1444 1447 1445 int KyraEngine_v2::seq_finaleFrash(WSAMovieV2 *wsaObj, int x, int y, int frm) { 1448 //uint32 endtime = 0;1449 1446 int tmp = 0; 1450 1447 1451 1448 switch (frm) { … … 1462 1459 case -1: 1463 1460 // if (_flags.isTalkie) 1464 1461 // seq_finaleActorScreen(); 1465 _seqSpecialFlag = true; 1462 _seqSpecialFlag = _flags.isTalkie; 1463 _seqRandomizeBase = 1; 1466 1464 break; 1467 1465 1468 1466 case 0: … … 1480 1478 if (_seqFrameCounter < 20 && _seqSpecialFlag) { 1481 1479 _seqWsaCurrentFrame = 0; 1482 1480 } else { 1483 _seqFrameDelay = 500;1481 _seqFrameDelay = _flags.isTalkie ? 500 : (300 + seq_generateFixedRandomValue(1, 300)); 1484 1482 seq_playTalkText(_flags.isTalkie ? 26 : 22); 1485 1483 if (_seqSpecialFlag) { 1486 1484 _seqFrameCounter = 3; … … 1495 1493 1496 1494 case 3: 1497 1495 seq_playTalkText(_flags.isTalkie ? 27 : 23); 1498 _seqFrameDelay = 500;1496 _seqFrameDelay = _flags.isTalkie ? 500 : (300 + seq_generateFixedRandomValue(1, 300)); 1499 1497 break; 1500 1498 1501 1499 case 4: … … 1506 1504 seq_playTalkText(_flags.isTalkie ? 27 : 23); 1507 1505 tmp = _seqFrameCounter / 6; 1508 1506 if (tmp == 2) 1509 _seqFrameDelay = 7;1507 _seqFrameDelay = _flags.isTalkie ? 7 : (1 + seq_generateFixedRandomValue(1, 10)); 1510 1508 else if (tmp < 2) 1511 _seqFrameDelay = 500;1509 _seqFrameDelay = _flags.isTalkie ? 500 : (300 + seq_generateFixedRandomValue(1, 300)); 1512 1510 break; 1513 1511 1514 1512 case 6: … … 1543 1541 _screen->loadBitmap("finale.cps", 3, 3, _screen->_currentPalette); 1544 1542 _screen->setFont(Screen::FID_GOLDFONT_FNT); 1545 1543 1546 _sound->setSoundFileList(_dosSoundFileList, _dosSoundFileListSize);1544 snd_assignMusicData(kMusicIngame); 1547 1545 _sound->loadSoundFile(3); 1548 1546 _sound->playTrack(3); 1549 1547 … … 1552 1550 1553 1551 // TODO 1554 1552 1555 _sound->setSoundFileList(_dosSoundFileListFinale, 1);1553 snd_assignMusicData(kMusicFinale); 1556 1554 _sound->loadSoundFile(0); 1557 1555 } 1558 1556 … … 2098 2096 } 2099 2097 2100 2098 void 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); 2102 2100 int entry = seq_setTextEntry(strIndex, x, y, dur, width); 2103 2101 _activeText[entry].textcolor = textColor; 2104 2102 uint32 chatTimeout = _system->getMillis() + dur * _tickLength; … … 2139 2137 curframe++; 2140 2138 } 2141 2139 2142 2143 2144 2140 if (lastframe < 0) { 2145 2141 int t = ABS(lastframe); 2146 2142 if (t < curframe) … … 2153 2149 _seqWsaCurrentFrame = curframe; 2154 2150 } 2155 2151 2152 int 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 2166 void 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 2156 2205 void KyraEngine_v2::seq_init() { 2157 2206 _seqProcessedString = new char[200]; 2158 2207 _seqWsa = new WSAMovieV2(this); 2159 2208 _activeWSA = new ActiveWSA[8]; 2160 2209 _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 } 2161 2227 } 2162 2228 2163 2229 void KyraEngine_v2::seq_uninit() { … … 2181 2247 void KyraEngine_v2::seq_makeBookOrCauldronAppear(int type) { 2182 2248 _screen->hideMouse(); 2183 2249 showMessage(0, 0xCF); 2184 2250 2185 2251 if (type == 1) { 2186 2252 seq_makeBookAppear(); 2187 2253 } else if (type == 2) { … … 2190 2256 2191 2257 _screen->copyRegionToBuffer(2, 0, 0, 320, 200, _screenBuffer); 2192 2258 _screen->loadBitmap("_PLAYALL.CPS", 3, 3, 0); 2193 2259 2194 2260 static int16 bookCauldronRects[] = { 2195 2261 0x46, 0x90, 0x7F, 0x2B, // unknown rect (maybe unused?) 2196 2262 0xCE, 0x90, 0x2C, 0x2C, // book rect … … 2215 2281 2216 2282 void KyraEngine_v2::seq_makeBookAppear() { 2217 2283 _screen->hideMouse(); 2218 2284 2219 2285 displayInvWsaLastFrame(); 2220 2286 2221 2287 showMessage(0, 0xCF); 2222 2288 2223 2289 loadInvWsa("BOOK2.WSA", 0, 4, 2, -1, -1, 0); 2224 2290 2225 2291 uint8 *rect = new uint8[_screen->getRectSize(_invWsa.w, _invWsa.h)]; 2226 2292 assert(rect); 2227 2293 2228 2294 _screen->copyRegionToBuffer(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect); 2229 2295 2230 2296 _invWsa.running = false; … … 2236 2302 2237 2303 while (true) { 2238 2304 _invWsa.timer = _system->getMillis() + _invWsa.delay * _tickLength; 2239 2305 2240 2306 _screen->copyBlockToPage(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect); 2241 2307 2242 2308 _invWsa.wsa->displayFrame(_invWsa.curFrame, 0x4000, 0, 0); 2243 2309 2244 2310 if (_invWsa.page) 2245 2311 _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, _invWsa.page, 0, Screen::CR_NO_P_CHECK); 2246 2312 2247 2313 ++_invWsa.curFrame; 2248 2314 2249 2315 if (_invWsa.curFrame >= _invWsa.lastFrame && !_quitFlag) 2250 2316 break; 2251 2317 2252 2318 switch (_invWsa.curFrame) { 2253 2319 case 39: 2254 2320 snd_playSoundEffect(0xCA); … … 2384 2450 2385 2451 } // end of namespace Kyra 2386 2452 2453 -
sound.h
52 52 #include "sound/softsynth/ym2612.h" 53 53 54 54 #include "kyra/kyra.h" 55 #include "kyra/kyra_v2.h" 55 56 56 57 namespace Audio { 57 58 class AudioStream; … … 59 60 60 61 namespace Kyra { 61 62 62 /** 63 /** 63 64 * Analog audio output device API for Kyrandia games. 64 65 * It countains functionallity to play music tracks, 65 66 * sound effects and voices. … … 109 110 virtual void setSoundFileList(const char * const *list, uint s) { _soundFileList = list; _soundFileListSize = s; } 110 111 111 112 /** 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 /** 112 122 * Load a specifc sound file for use of 113 123 * playing music and sound effects. 114 124 */ … … 161 171 * 162 172 * @param file file to be played 163 173 */ 164 v oid voicePlay(const char *file);174 virtual void voicePlay(const char *file); 165 175 166 176 /** 167 177 * Checks if a voice is being played. … … 180 190 int _musicEnabled; 181 191 bool _sfxEnabled; 182 192 193 int _currentTheme; 194 183 195 KyraEngine *_vm; 184 196 Audio::Mixer *_mixer; 185 197 … … 213 225 * Dune II, Kyrandia 1 and 2. While Dune II and 214 226 * Kyrandia 1 are using exact the same format, the 215 227 * one of Kyrandia 2 slightly differs. 216 * 228 * 217 229 * See AdlibDriver for more information. 218 230 * @see AdlibDriver 219 231 */ … … 268 280 * 269 281 * Currently it does not initialize the MT-32 output properly, 270 282 * so MT-32 output does sound a bit odd in some cases. 271 * 283 * 272 284 * TODO: this code needs some serious cleanup and rework 273 285 * to support MT-32 and GM properly. 274 286 */ … … 341 353 Common::Mutex _mutex; 342 354 }; 343 355 344 class FMT_EuphonyDriver;356 class SoundTowns_EuphonyDriver; 345 357 class SoundTowns : public MidiDriver, public Sound { 346 358 public: 347 359 SoundTowns(KyraEngine *vm, Audio::Mixer *mixer); … … 350 362 bool init(); 351 363 void process(); 352 364 353 void setVolume(int) { /* TODO */}354 int getVolume() { return 255; /* TODO */}365 void setVolume(int) {} 366 int getVolume() { return 255; } 355 367 368 void setMusicVolume(int volume); 369 void setSoundEffectsVolume(int volume) { _sfxVolume = (uint8) volume; } 370 356 371 void loadSoundFile(uint file); 357 372 358 373 void playTrack(uint8 track); … … 387 402 Audio::AudioStream *_currentSFX; 388 403 Audio::SoundHandle _sfxHandle; 389 404 390 int _currentTrackTable;391 405 uint _sfxFileIndex; 392 406 uint8 *_sfxFileData; 407 uint8 _sfxVolume; 393 408 394 FMT_EuphonyDriver * _driver;409 SoundTowns_EuphonyDriver * _driver; 395 410 MidiParser * _parser; 396 uint8 *_musicTrackData;397 411 398 412 Common::Mutex _mutex; 399 413 400 static const char *_sfxFiles[];401 static const int _sfxFilenum;402 414 static const uint8 _sfxBTTable[256]; 403 415 const uint8 *_sfxWDTable; 404 416 }; 405 417 418 //class SoundTowns_v2_TwnDriver; 419 class SoundTowns_v2: public Sound { 420 public: 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 442 private: 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 406 463 class MixedSoundDriver : public Sound { 407 464 public: 408 465 MixedSoundDriver(KyraEngine *vm, Audio::Mixer *mixer, Sound *music, Sound *sfx) : Sound(vm, mixer), _music(music), _sfx(sfx) {} -
sound_towns.cpp
33 33 #include "sound/audiostream.h" 34 34 35 35 #include "common/util.h" 36 36 37 #include <math.h> 37 38 39 #define EUPHONY_FADEOUT_TICKS 600 40 38 41 namespace Kyra { 39 42 40 enum EuD_ChannelState { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing };43 enum ChannelState { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing }; 41 44 42 45 class MidiChannel_EuD : public MidiChannel { 43 46 public: … … 125 128 const int8 *_samples; 126 129 } * _snd[8]; 127 130 struct Env { 128 EuD_ChannelState state;131 ChannelState state; 129 132 int32 currentLevel; 130 133 int32 rate; 131 134 int32 tickCount; … … 142 145 } * _voice; 143 146 }; 144 147 148 class SoundTowns_EuphonyTrackQueue { 149 public: 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 166 private: 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 145 176 class MidiParser_EuD : public MidiParser { 146 177 public: 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); 150 180 int32 calculateTempo(int16 val); 151 181 152 182 protected: 153 183 void parseNextEvent (EventInfo &info); 154 184 void resetTracking(); 185 void setup(); 155 186 156 187 byte * _enable; 157 188 byte * _mode; … … 159 190 byte * _adjVelo; 160 191 int8 * _adjNote; 161 192 162 byte _tempo[3];163 164 193 uint8 _firstBaseTickStep; 165 194 uint8 _nextBaseTickStep; 166 195 uint32 _initialTempo; 167 196 uint32 _baseTick; 197 198 byte _tempo[3]; 199 SoundTowns_EuphonyTrackQueue * _queue; 168 200 }; 169 201 170 class FMT_EuphonyDriver : public MidiDriver_Emulated {202 class SoundTowns_EuphonyDriver : public MidiDriver_Emulated { 171 203 public: 172 FMT_EuphonyDriver(Audio::Mixer *mixer);173 virtual ~ FMT_EuphonyDriver();204 SoundTowns_EuphonyDriver(Audio::Mixer *mixer); 205 virtual ~SoundTowns_EuphonyDriver(); 174 206 175 207 int open(); 176 208 void close(); … … 179 211 uint32 property(int prop, uint32 param) { return 0; } 180 212 181 213 void setPitchBendRange(byte channel, uint range) { } 182 //void sysEx(const byte *msg, uint16 length);183 214 void loadFmInstruments(const byte *instr); 184 215 void loadWaveInstruments(const byte *instr); 185 216 217 SoundTowns_EuphonyTrackQueue * queue() { return _queue; } 218 186 219 MidiChannel *allocateChannel() { return 0; } 187 220 MidiChannel *getPercussionChannel() { return 0; } 188 221 … … 190 223 void assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber); 191 224 void removeChannel(uint8 midiChannelNumber); 192 225 226 void setVolume(int val = -1) { if (val >= 0) _volume = val; } 227 int getVolume(int val = -1) { return _volume; } 228 193 229 // AudioStream API 194 230 bool isStereo() const { return true; } 195 231 int getRate() const { return _mixer->getOutputRate(); } … … 198 234 199 235 protected: 200 236 void nextTick(int16 *buf1, int buflen); 201 int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; }202 237 void rate(uint16 r); 203 238 204 239 void generateSamples(int16 *buf, int len); … … 206 241 MidiChannel_EuD_FM *_fChannel[6]; 207 242 MidiChannel_EuD_WAVE *_wChannel[8]; 208 243 MidiChannel_EuD * _channel[16]; 244 SoundTowns_EuphonyTrackQueue * _queue; 209 245 210 246 int _volume; 211 247 bool _fading; … … 532 568 _velocity = velo; 533 569 } 534 570 535 FMT_EuphonyDriver::FMT_EuphonyDriver(Audio::Mixer *mixer)571 SoundTowns_EuphonyDriver::SoundTowns_EuphonyDriver(Audio::Mixer *mixer) 536 572 : MidiDriver_Emulated(mixer) { 537 573 538 574 _volume = 255; 539 _fadestate = 300; 575 _fadestate = EUPHONY_FADEOUT_TICKS; 576 _queue = 0; 540 577 541 578 MidiDriver_YM2612::createLookupTables(); 542 579 … … 551 588 552 589 rate(getRate()); 553 590 fading(0); 591 592 _queue = new SoundTowns_EuphonyTrackQueue(this, 0); 554 593 } 555 594 556 FMT_EuphonyDriver::~FMT_EuphonyDriver() {595 SoundTowns_EuphonyDriver::~SoundTowns_EuphonyDriver() { 557 596 for (int i = 0; i < 6; i++) 558 597 delete _fChannel[i]; 559 598 for (int i = 0; i < 8; i++) … … 577 616 _waveSounds[i] = 0; 578 617 } 579 618 } 619 620 if (_queue) { 621 _queue->release(); 622 delete _queue; 623 _queue = 0; 624 } 580 625 } 581 626 582 int FMT_EuphonyDriver::open() {627 int SoundTowns_EuphonyDriver::open() { 583 628 if (_isOpen) 584 629 return MERR_ALREADY_OPEN; 585 586 630 MidiDriver_Emulated::open(); 587 631 588 632 _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, 589 633 this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); 634 590 635 return 0; 591 636 } 592 637 593 void FMT_EuphonyDriver::close() {638 void SoundTowns_EuphonyDriver::close() { 594 639 if (!_isOpen) 595 640 return; 596 641 _isOpen = false; 597 642 _mixer->stopHandle(_mixerSoundHandle); 598 643 } 599 644 600 void FMT_EuphonyDriver::send(uint32 b) {645 void SoundTowns_EuphonyDriver::send(uint32 b) { 601 646 send(b & 0xF, b & 0xFFFFFFF0); 602 647 } 603 648 604 void FMT_EuphonyDriver::send(byte chan, uint32 b) { 605 //byte param3 = (byte) ((b >> 24) & 0xFF); 606 649 void SoundTowns_EuphonyDriver::send(byte chan, uint32 b) { 607 650 byte param2 = (byte) ((b >> 16) & 0xFF); 608 651 byte param1 = (byte) ((b >> 8) & 0xFF); 609 652 byte cmd = (byte) (b & 0xF0); … … 662 705 _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000); 663 706 break; 664 707 default: 665 warning(" FMT_EuphonyDriver: Unknown send() command 0x%02X", cmd);708 warning("SoundTowns_EuphonyDriver: Unknown send() command 0x%02X", cmd); 666 709 } 667 710 } 668 711 669 void FMT_EuphonyDriver::loadFmInstruments(const byte *instr) {712 void SoundTowns_EuphonyDriver::loadFmInstruments(const byte *instr) { 670 713 if (_fmInstruments) 671 714 delete [] _fmInstruments; 672 715 _fmInstruments = new uint8[0x1800]; 673 716 memcpy(_fmInstruments, instr, 0x1800); 674 717 } 675 718 676 void FMT_EuphonyDriver::loadWaveInstruments(const byte *instr) {719 void SoundTowns_EuphonyDriver::loadWaveInstruments(const byte *instr) { 677 720 if (_waveInstruments) 678 721 delete [] _waveInstruments; 679 722 _waveInstruments = new uint8[0x1000]; … … 698 741 } 699 742 700 743 701 void FMT_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) {744 void SoundTowns_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) { 702 745 _channel[midiChannelNumber] = _fChannel[fmChannelNumber]; 703 746 } 704 747 705 void FMT_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) {748 void SoundTowns_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) { 706 749 _channel[midiChannelNumber] = _wChannel[waveChannelNumber]; 707 750 } 708 751 709 void FMT_EuphonyDriver::removeChannel(uint8 midiChannelNumber) {752 void SoundTowns_EuphonyDriver::removeChannel(uint8 midiChannelNumber) { 710 753 _channel[midiChannelNumber] = 0; 711 754 } 712 755 713 void FMT_EuphonyDriver::generateSamples(int16 *data, int len) {756 void SoundTowns_EuphonyDriver::generateSamples(int16 *data, int len) { 714 757 memset(data, 0, 2 * sizeof(int16) * len); 715 758 nextTick(data, len); 716 759 } 717 760 718 void FMT_EuphonyDriver::nextTick(int16 *buf1, int buflen) {761 void SoundTowns_EuphonyDriver::nextTick(int16 *buf1, int buflen) { 719 762 int32 *buf0 = (int32 *)buf1; 720 763 721 764 for (int i = 0; i < ARRAYSIZE(_channel); i++) { … … 724 767 } 725 768 726 769 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) ); 728 771 buf1[i*2] = buf1[i*2+1] = (s >> 9) & 0xffff; 729 772 } 730 773 731 774 if (_fading) { 732 if (_fadestate) 775 if (_fadestate) { 733 776 _fadestate--; 734 else777 } else { 735 778 _fading = false; 779 _queue->setPlayBackStatus(false); 780 } 736 781 } 737 782 } 738 783 739 void FMT_EuphonyDriver::rate(uint16 r) {784 void SoundTowns_EuphonyDriver::rate(uint16 r) { 740 785 for (uint8 i = 0; i < 16; i++) { 741 786 if (_channel[i]) 742 787 _channel[i]->rate(r); 743 788 } 744 789 } 745 790 746 void FMT_EuphonyDriver::fading(bool status) {791 void SoundTowns_EuphonyDriver::fading(bool status) { 747 792 _fading = status; 748 793 if (!_fading) 749 _fadestate = 300;794 _fadestate = EUPHONY_FADEOUT_TICKS; 750 795 } 751 796 752 MidiParser_EuD::MidiParser_EuD( ) : MidiParser(),797 MidiParser_EuD::MidiParser_EuD(SoundTowns_EuphonyTrackQueue * queue) : MidiParser(), 753 798 _firstBaseTickStep(0x33), _nextBaseTickStep(0x33) { 754 799 _initialTempo = calculateTempo(0x5a); 800 _queue = queue; 755 801 } 756 802 757 803 void MidiParser_EuD::parseNextEvent(EventInfo &info) { 758 804 byte *pos = _position._play_pos; 759 805 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 760 827 while (true) { 761 828 byte cmd = *pos; 762 829 byte evt = (cmd & 0xF0); … … 830 897 break; 831 898 } else if (cmd == 0xFD || cmd == 0xFE) { 832 899 // End of track. 833 if (_autoLoop) 900 if (_autoLoop) { 901 unloadMusic(); 902 _queue->setPlayBackStatus(true); 834 903 pos = info.start = _tracks[0]; 835 else904 } else { 836 905 info.start = pos; 906 } 837 907 838 908 uint32 last = _position._last_event_tick; 839 909 uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick; … … 852 922 _position._play_pos = pos; 853 923 } 854 924 855 bool MidiParser_EuD::loadMusic(byte *data, uint32 ) {856 unloadMusic();925 bool MidiParser_EuD::loadMusic(byte *data, uint32 size) { 926 bool loop = _autoLoop; 857 927 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 } 874 939 return true; 875 940 } 876 941 … … 892 957 893 958 void MidiParser_EuD::resetTracking() { 894 959 MidiParser::resetTracking(); 960 895 961 _nextBaseTickStep = _firstBaseTickStep; 896 962 _baseTick = 0; 897 963 setTempo(_initialTempo); 964 _queue->setPlayBackStatus(false); 898 965 } 899 966 967 void 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 989 SoundTowns_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 998 void 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 1006 SoundTowns_EuphonyTrackQueue * SoundTowns_EuphonyTrackQueue::reset() { 1007 SoundTowns_EuphonyTrackQueue * i = this; 1008 while (i->_last) 1009 i = i->_last; 1010 return i; 1011 } 1012 1013 void 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 1027 void 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 1049 void 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 1071 void 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 900 1089 SoundTowns::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) { 902 1091 903 _driver = new FMT_EuphonyDriver(_mixer);1092 _driver = new SoundTowns_EuphonyDriver(_mixer); 904 1093 int ret = open(); 905 1094 if (ret != MERR_ALREADY_OPEN && ret != 0) { 906 1095 error("couldn't open midi driver"); … … 916 1105 _driver->setTimerCallback(0, 0); 917 1106 close(); 918 1107 919 if (_musicTrackData)920 delete [] _musicTrackData;921 922 1108 _driver = 0; 923 1109 } 924 1110 … … 950 1136 track -= 2; 951 1137 952 1138 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 } 1012 1159 }; 1013 1160 1014 1161 int trackNum = tTable[track].track; … … 1017 1164 if (track == _lastTrack && _musicEnabled) 1018 1165 return; 1019 1166 1020 haltTrack();1167 beginFadeOut(); 1021 1168 1022 1169 if (_musicEnabled == 2 && trackNum != -1) { 1023 1170 AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0); … … 1035 1182 AudioCD.updateCD(); 1036 1183 if (_parser) { 1037 1184 Common::StackLock lock(_mutex); 1038 1039 1185 _parser->setTrack(0); 1040 1186 _parser->jumpToTick(0); 1041 1042 1187 _parser->unloadMusic(); 1043 1188 delete _parser; 1044 1189 _parser = 0; 1045 1046 1190 setVolume(255); 1047 1191 } 1192 _driver->queue()->release(); 1048 1193 } 1049 1194 1195 void SoundTowns::setMusicVolume(int volume) { 1196 _driver->setVolume(volume); 1197 } 1198 1050 1199 void SoundTowns::loadSoundFile(uint file) { 1051 1200 if (_sfxFileIndex == file) 1052 1201 return; … … 1143 1292 1144 1293 _currentSFX = Audio::makeLinearInputStream(sfxPlaybackBuffer, playbackBufferSize, 1145 1294 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); 1147 1296 } 1148 1297 1149 1298 void SoundTowns::beginFadeOut() { … … 1181 1330 } 1182 1331 1183 1332 bool SoundTowns::loadInstruments() { 1184 if (!_musicTrackData)1185 _musicTrackData = new uint8[0xC58A];1186 1187 memset(_musicTrackData, 0, 0xC58A);1188 1333 uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0); 1189 1334 if (!twm) 1190 1335 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); 1193 1338 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); 1196 1341 delete [] twm; 1197 _driver-> loadWaveInstruments(_musicTrackData + 8);1342 _driver->queue()->release(); 1198 1343 1199 1344 return true; 1200 1345 } 1201 1346 1202 1347 void SoundTowns::playEuphonyTrack(uint32 offset, int loop) { 1203 if (!_musicTrackData)1204 _musicTrackData = new uint8[0xC58A];1205 1206 memset(_musicTrackData, 0, 0xC58A);1207 1348 uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0); 1208 Screen::decodeFrame4(twm + 0x4b70 + offset, _musicTrackData, 0xC58A);1209 delete [] twm;1210 1349 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()); 1220 1354 } 1221 1355 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;1237 1356 _parser->property(MidiParser::mpAutoLoop, loop); 1238 _parser->loadMusic(_musicTrackData, 0); 1239 _parser->jumpToTick(0); 1357 _parser->loadMusic(twm + 0x4b70 + offset, 0xC58A); 1240 1358 1241 _parser->setMidiDriver(this); 1242 _parser->setTimerRate(getBaseTempo()); 1359 delete [] twm; 1243 1360 } 1244 1361 1245 1362 void SoundTowns::onTimer(void * data) { … … 1302 1419 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 1303 1420 }; 1304 1421 1422 // KYRA 2 1423 1424 SoundTowns_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 1429 SoundTowns_v2::~SoundTowns_v2() { 1430 /*if (_driver) 1431 delete _driver;*/ 1432 if (_twnTrackData) 1433 delete [] _twnTrackData; 1434 } 1435 1436 bool 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 1446 void SoundTowns_v2::process() { 1447 AudioCD.updateCD(); 1448 } 1449 1450 void SoundTowns_v2::setMusicVolume(int volume) { 1451 /* TODO */ 1452 } 1453 1454 void 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 1486 void SoundTowns_v2::haltTrack() { 1487 _lastTrack = -1; 1488 AudioCD.stop(); 1489 AudioCD.updateCD(); 1490 //_driver->reset(); 1491 } 1492 1493 void 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 1548 void SoundTowns_v2::beginFadeOut() { 1549 //_driver->fadeOut(); 1550 haltTrack(); 1551 } 1552 1553 const uint8 SoundTowns_v2::_cdaTrackTableK2Intro[] = { 1554 0x03, 0x01, 0x04, 0x02, 0x05, 0x03, 0x06, 0x04, 0x07, 0x05, 0x08, 0x06 1555 }; 1556 1557 const 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 1570 const uint8 SoundTowns_v2::_cdaTrackTableK2Finale[] = { 1571 0x03, 0x53, 0x04, 0x54 1572 }; 1573 1574 const 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 1305 1580 } // end of namespace Kyra 1306 1581 1582 #undef EUPHONY_FADEOUT_TICKS 1583