Ticket #8757: kyraSoundTownsEtc.patch
File kyraSoundTownsEtc.patch, 42.7 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 -
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 -
kyra_v2.cpp
36 36 37 37 #include "common/system.h" 38 38 39 #if _MSC_VER >= 1400 40 #define sprintf sprintf_s 41 #define strcpy(a, b) strcpy_s((a), strlen((b)) + 1, (b)) 42 #define strcat(a, b) strcat_s((a), strlen((a)) + strlen((b)) + 1, (b)) 43 #endif 44 39 45 namespace Kyra { 40 46 41 47 KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags), _updateFunctor(this, &KyraEngine_v2::update) { … … 113 119 114 120 KyraEngine::init(); 115 121 122 if (!_sound->init()) 123 error("Couldn't init sound"); 124 116 125 _debugger = new Debugger_v2(this); 117 126 assert(_debugger); 118 127 _text = new TextDisplayer_v2(this, _screen); … … 145 154 } 146 155 147 156 for (int i = 0; i < 33; i++) 148 _sequenceStringsDuration[i] = strlen(_sequenceStrings[i]) * 8;157 _sequenceStringsDuration[i] = (int) strlen(_sequenceStrings[i]) * 8; 149 158 150 159 // No mouse display in demo 151 160 if (_flags.isDemo) … … 164 173 } 165 174 166 175 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"); 176 if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) 177 seq_showStarcraftLogo(); 171 178 172 179 seq_playSequences(kSequenceVirgin, kSequenceZanfaun); 173 180 //seq_playSequences(kSequenceFunters, kSequenceFrash); … … 175 182 if (_menuChoice == 1) { 176 183 // load just the pak files needed for ingame 177 184 _res->unloadAllPakFiles(); 178 _res->loadFileList("FILEDATA.FDT"); 185 if (_flags.isTalkie) { 186 _res->loadFileList("FILEDATA.FDT"); 187 } else { 188 char tmpfilename[13]; 189 static const char * pakfiles [] = { "KYRA.DAT", "AUDIO.PAK", "CAULDRON.PAK", 190 "MISC_CPS.PAK", "MISC_EMC.PAK", "OTHER.PAK", "VOC.PAK", "WSCORE.PAK" }; 191 for (int i = 0; i < 8; i++) 192 _res->loadPakFile(pakfiles[i]); 193 for (int i = 1; i < 10; i++) { 194 sprintf(tmpfilename, "COST%d_SH.PAK", i); 195 _res->loadPakFile(tmpfilename); 196 } 197 for (int i = 1; i < 6; i++) { 198 sprintf(tmpfilename, "HOFCH_%d.PAK", i); 199 _res->loadPakFile(tmpfilename); 200 } 201 } 202 179 203 startup(); 180 204 runLoop(); 181 205 cleanup(); … … 187 211 } 188 212 189 213 void KyraEngine_v2::startup() { 190 _sound->setSoundFileList(_dosSoundFileList, _dosSoundFileListSize); 214 snd_assignMusicData(k2MusicIngame); 215 // The track map is exactly the same 216 // for FM-TOWNS and DOS 191 217 _trackMap = _dosTrackMap; 192 218 _trackMapSize = _dosTrackMapSize; 193 219 … … 306 332 // waitTicks(5); 307 333 // sub_270A0(); 308 334 //} 309 335 310 336 if (_system->getMillis() > _nextIdleAnim) 311 337 showIdleAnim(); 312 338 … … 1540 1566 _sound->loadSoundFile(file); 1541 1567 } 1542 1568 1569 void KyraEngine_v2::snd_assignMusicData(k2MusicDataID id) { 1570 if (_flags.isTalkie) { 1571 if (id == k2MusicIntro) 1572 _sound->setSoundFileList(_dosSoundFileListIntro, 1); 1573 else if (id == k2MusicFinale) 1574 _sound->setSoundFileList(_dosSoundFileListFinale, 1); 1575 else 1576 _sound->setSoundFileList(_dosSoundFileList, _dosSoundFileListSize); 1577 } else { 1578 ((SoundTowns_v2*)_sound)->assignMusicData((int) id); 1579 } 1580 } 1581 1543 1582 void KyraEngine_v2::playVoice(int high, int low) { 1544 1583 int vocFile = high * 10000 + low * 10; 1545 1584 snd_playVoiceFile(vocFile); … … 1632 1671 case 48: 1633 1672 snd_playSoundEffect(0x38); 1634 1673 break; 1635 1674 1636 1675 default: 1637 1676 break; 1638 1677 } … … 1904 1943 1905 1944 } // end of namespace Kyra 1906 1945 1907 1946 #if _MSC_VER >= 1400 1947 #undef sprintf 1948 #undef strcpy 1949 #undef strcat 1950 #endif 1951 No newline at end of file -
kyra_v2.h
74 74 kSequenceHand4 75 75 }; 76 76 77 enum k2MusicDataID { 78 k2MusicIntro = 0, 79 k2MusicIngame, 80 k2MusicFinale 81 }; 77 82 class WSAMovieV2; 78 83 class KyraEngine_v2; 79 84 class TextDisplayer_v2; … … 225 230 void seq_printCreditsString(uint16 strIndex, int x, int y, uint8 * colorMap, uint8 textcolor); 226 231 void seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, 227 232 WSAMovieV2 * wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos); 233 int seq_generateFixedRandomValue(int rangeFirst, int rangeLast); 234 void seq_showStarcraftLogo(); 228 235 229 236 void seq_init(); 230 237 void seq_uninit(); … … 246 253 static const int8 _dosTrackMap[]; 247 254 static const int _dosTrackMapSize; 248 255 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 256 protected: 257 257 // game initialization 258 258 void startup(); … … 628 628 629 629 virtual void snd_playVoiceFile(int id); 630 630 void snd_loadSoundFile(int id); 631 void snd_assignMusicData(k2MusicDataID id); 631 632 632 633 void playVoice(int high, int low); 633 634 … … 639 640 void timerFunc6(int); 640 641 641 642 void setTimer1DelaySecs(int secs); 642 643 643 644 uint32 _nextIdleAnim; 644 645 int _lastIdleScript; 645 646 … … 846 847 static const int _sequenceStringsSize_TOWNS_EN; 847 848 static const char *_sequenceStrings_PC_EN[]; 848 849 static const int _sequenceStringsSize_PC_EN; 850 static const char _actorScreenStrings_PC_EN[]; 851 static const int _actorScreenStringsSize_PC_EN; 849 852 850 853 int _sequenceStringsDuration[33]; 851 854 … … 861 864 int _seqFrameCounter; 862 865 int _seqWsaCurrentFrame; 863 866 bool _seqSpecialFlag; 867 int _seqRandomizeBase; 864 868 bool _seqSubframePlaying; 865 869 uint8 _seqTextColor[2]; 866 870 uint8 _seqTextColorMap[16]; -
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) ? k2MusicFinale : k2MusicIntro); 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(k2MusicIngame); 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(k2MusicFinale); 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 if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { 2223 _res->loadPakFile("INTROVOC.PAK"); 2224 _res->loadPakFile("WSCORE.PAK"); 2225 } 2161 2226 } 2162 2227 2163 2228 void KyraEngine_v2::seq_uninit() { … … 2181 2246 void KyraEngine_v2::seq_makeBookOrCauldronAppear(int type) { 2182 2247 _screen->hideMouse(); 2183 2248 showMessage(0, 0xCF); 2184 2249 2185 2250 if (type == 1) { 2186 2251 seq_makeBookAppear(); 2187 2252 } else if (type == 2) { … … 2190 2255 2191 2256 _screen->copyRegionToBuffer(2, 0, 0, 320, 200, _screenBuffer); 2192 2257 _screen->loadBitmap("_PLAYALL.CPS", 3, 3, 0); 2193 2258 2194 2259 static int16 bookCauldronRects[] = { 2195 2260 0x46, 0x90, 0x7F, 0x2B, // unknown rect (maybe unused?) 2196 2261 0xCE, 0x90, 0x2C, 0x2C, // book rect … … 2215 2280 2216 2281 void KyraEngine_v2::seq_makeBookAppear() { 2217 2282 _screen->hideMouse(); 2218 2283 2219 2284 displayInvWsaLastFrame(); 2220 2285 2221 2286 showMessage(0, 0xCF); 2222 2287 2223 2288 loadInvWsa("BOOK2.WSA", 0, 4, 2, -1, -1, 0); 2224 2289 2225 2290 uint8 *rect = new uint8[_screen->getRectSize(_invWsa.w, _invWsa.h)]; 2226 2291 assert(rect); 2227 2292 2228 2293 _screen->copyRegionToBuffer(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect); 2229 2294 2230 2295 _invWsa.running = false; … … 2236 2301 2237 2302 while (true) { 2238 2303 _invWsa.timer = _system->getMillis() + _invWsa.delay * _tickLength; 2239 2304 2240 2305 _screen->copyBlockToPage(_invWsa.page, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, rect); 2241 2306 2242 2307 _invWsa.wsa->displayFrame(_invWsa.curFrame, 0x4000, 0, 0); 2243 2308 2244 2309 if (_invWsa.page) 2245 2310 _screen->copyRegion(_invWsa.x, _invWsa.y, _invWsa.x, _invWsa.y, _invWsa.w, _invWsa.h, _invWsa.page, 0, Screen::CR_NO_P_CHECK); 2246 2311 2247 2312 ++_invWsa.curFrame; 2248 2313 2249 2314 if (_invWsa.curFrame >= _invWsa.lastFrame && !_quitFlag) 2250 2315 break; 2251 2316 2252 2317 switch (_invWsa.curFrame) { 2253 2318 case 39: 2254 2319 snd_playSoundEffect(0xCA); -
sound.h
59 59 60 60 namespace Kyra { 61 61 62 /** 62 /** 63 63 * Analog audio output device API for Kyrandia games. 64 64 * It countains functionallity to play music tracks, 65 65 * sound effects and voices. … … 161 161 * 162 162 * @param file file to be played 163 163 */ 164 v oid voicePlay(const char *file);164 virtual void voicePlay(const char *file); 165 165 166 166 /** 167 167 * Checks if a voice is being played. … … 213 213 * Dune II, Kyrandia 1 and 2. While Dune II and 214 214 * Kyrandia 1 are using exact the same format, the 215 215 * one of Kyrandia 2 slightly differs. 216 * 216 * 217 217 * See AdlibDriver for more information. 218 218 * @see AdlibDriver 219 219 */ … … 268 268 * 269 269 * Currently it does not initialize the MT-32 output properly, 270 270 * so MT-32 output does sound a bit odd in some cases. 271 * 271 * 272 272 * TODO: this code needs some serious cleanup and rework 273 273 * to support MT-32 and GM properly. 274 274 */ … … 341 341 Common::Mutex _mutex; 342 342 }; 343 343 344 class FMT_EuphonyDriver;344 class SoundTowns_EuphonyDriver; 345 345 class SoundTowns : public MidiDriver, public Sound { 346 346 public: 347 347 SoundTowns(KyraEngine *vm, Audio::Mixer *mixer); … … 350 350 bool init(); 351 351 void process(); 352 352 353 void setVolume(int) { /* TODO */}354 int getVolume() { return 255; /* TODO */}353 void setVolume(int) {} 354 int getVolume() { return 255; } 355 355 356 void setMusicVolume(int volume); 357 void setSoundEffectsVolume(int volume) { _sfxVolume = (uint8) volume; } 358 356 359 void loadSoundFile(uint file); 357 360 358 361 void playTrack(uint8 track); … … 387 390 Audio::AudioStream *_currentSFX; 388 391 Audio::SoundHandle _sfxHandle; 389 392 390 int _currentTrackTable;391 393 uint _sfxFileIndex; 392 394 uint8 *_sfxFileData; 395 uint8 _sfxVolume; 393 396 394 FMT_EuphonyDriver * _driver;397 SoundTowns_EuphonyDriver * _driver; 395 398 MidiParser * _parser; 396 uint8 *_musicTrackData;397 399 398 400 Common::Mutex _mutex; 399 401 400 static const char *_sfxFiles[];401 static const int _sfxFilenum;402 402 static const uint8 _sfxBTTable[256]; 403 403 const uint8 *_sfxWDTable; 404 404 }; 405 405 406 } // end of namespace Kyra 407 408 struct Kyra2AudioThemes { 409 const uint8 * cdaTable; 410 const uint8 cdaTableSize; 411 const char * twnFilename; 412 }; 413 414 namespace Kyra { 415 416 //class SoundTowns_v2_TwnDriver; 417 class SoundTowns_v2: public Sound { 418 public: 419 SoundTowns_v2(KyraEngine *vm, Audio::Mixer *mixer); 420 ~SoundTowns_v2(); 421 422 bool init(); 423 void process(); 424 425 void setVolume(int) {} 426 int getVolume() { return 255; } 427 428 void setMusicVolume(int volume); 429 void setSoundEffectsVolume(int volume) { _sfxVolume = (uint8) volume; } 430 431 void loadSoundFile(uint file) {} 432 void assignMusicData (int id) { _currentTheme = id; } 433 434 void playTrack(uint8 track); 435 void haltTrack(); 436 void beginFadeOut(); 437 438 void voicePlay(const char *file); 439 void playSoundEffect(uint8) {} 440 441 private: 442 int _lastTrack; 443 int _currentTheme; 444 445 Audio::AudioStream *_currentSFX; 446 Audio::SoundHandle _sfxHandle; 447 uint8 _sfxVolume; 448 449 //SoundTowns_v2_TwnDriver * _driver; 450 uint8 * _twnTrackData; 451 452 static const uint8 _cdaTrackTableK2Intro[]; 453 static const uint8 _cdaTrackTableK2Ingame[]; 454 static const uint8 _cdaTrackTableK2Finale[]; 455 static const Kyra2AudioThemes _themes[]; 456 }; 457 406 458 class MixedSoundDriver : public Sound { 407 459 public: 408 460 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 37 #if _MSC_VER >= 1400 38 #define sprintf sprintf_s 39 #endif 40 36 41 #include <math.h> 37 42 43 #define EUPHONY_FADEOUT_TICKS 600 44 38 45 namespace Kyra { 39 46 40 enum EuD_ChannelState { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing };47 enum ChannelState { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing }; 41 48 42 49 class MidiChannel_EuD : public MidiChannel { 43 50 public: … … 125 132 const int8 *_samples; 126 133 } * _snd[8]; 127 134 struct Env { 128 EuD_ChannelState state;135 ChannelState state; 129 136 int32 currentLevel; 130 137 int32 rate; 131 138 int32 tickCount; … … 142 149 } * _voice; 143 150 }; 144 151 152 class SoundTowns_EuphonyTrackQueue { 153 public: 154 SoundTowns_EuphonyTrackQueue::SoundTowns_EuphonyTrackQueue 155 (SoundTowns_EuphonyDriver * driver, SoundTowns_EuphonyTrackQueue * last); 156 SoundTowns_EuphonyTrackQueue::~SoundTowns_EuphonyTrackQueue() {} 157 158 void release(); 159 void initDriver(); 160 void loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop = 0); 161 void loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop = 0); 162 void setPlayBackStatus(bool playing); 163 SoundTowns_EuphonyTrackQueue * reset(); 164 bool isPlaying() {return _playing; } 165 uint8 * trackData() {return _trackData; } 166 167 bool _loop; 168 SoundTowns_EuphonyTrackQueue * _next; 169 170 private: 171 uint8 * _trackData; 172 uint8 * _used; 173 uint8 * _fchan; 174 uint8 * _wchan; 175 bool _playing; 176 SoundTowns_EuphonyDriver * _driver; 177 SoundTowns_EuphonyTrackQueue * _last; 178 }; 179 145 180 class MidiParser_EuD : public MidiParser { 146 181 public: 147 MidiParser_EuD(); 148 149 bool loadMusic (byte *data, uint32 unused = 0); 182 MidiParser_EuD(SoundTowns_EuphonyTrackQueue * queue); 183 bool loadMusic (byte *data, uint32 size); 150 184 int32 calculateTempo(int16 val); 151 185 152 186 protected: 153 187 void parseNextEvent (EventInfo &info); 154 188 void resetTracking(); 189 void setup(); 155 190 156 191 byte * _enable; 157 192 byte * _mode; … … 159 194 byte * _adjVelo; 160 195 int8 * _adjNote; 161 196 162 byte _tempo[3];163 164 197 uint8 _firstBaseTickStep; 165 198 uint8 _nextBaseTickStep; 166 199 uint32 _initialTempo; 167 200 uint32 _baseTick; 201 202 byte _tempo[3]; 203 SoundTowns_EuphonyTrackQueue * _queue; 168 204 }; 169 205 170 class FMT_EuphonyDriver : public MidiDriver_Emulated {206 class SoundTowns_EuphonyDriver : public MidiDriver_Emulated { 171 207 public: 172 FMT_EuphonyDriver(Audio::Mixer *mixer);173 virtual ~ FMT_EuphonyDriver();208 SoundTowns_EuphonyDriver(Audio::Mixer *mixer); 209 virtual ~SoundTowns_EuphonyDriver(); 174 210 175 211 int open(); 176 212 void close(); … … 179 215 uint32 property(int prop, uint32 param) { return 0; } 180 216 181 217 void setPitchBendRange(byte channel, uint range) { } 182 //void sysEx(const byte *msg, uint16 length);183 218 void loadFmInstruments(const byte *instr); 184 219 void loadWaveInstruments(const byte *instr); 185 220 221 SoundTowns_EuphonyTrackQueue * queue() { return _queue; } 222 186 223 MidiChannel *allocateChannel() { return 0; } 187 224 MidiChannel *getPercussionChannel() { return 0; } 188 225 … … 190 227 void assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber); 191 228 void removeChannel(uint8 midiChannelNumber); 192 229 230 void setVolume(int val = -1) { if (val >= 0) _volume = val; } 231 int getVolume(int val = -1) { return _volume; } 232 193 233 // AudioStream API 194 234 bool isStereo() const { return true; } 195 235 int getRate() const { return _mixer->getOutputRate(); } … … 198 238 199 239 protected: 200 240 void nextTick(int16 *buf1, int buflen); 201 int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; }202 241 void rate(uint16 r); 203 242 204 243 void generateSamples(int16 *buf, int len); … … 206 245 MidiChannel_EuD_FM *_fChannel[6]; 207 246 MidiChannel_EuD_WAVE *_wChannel[8]; 208 247 MidiChannel_EuD * _channel[16]; 248 SoundTowns_EuphonyTrackQueue * _queue; 209 249 210 250 int _volume; 211 251 bool _fading; … … 532 572 _velocity = velo; 533 573 } 534 574 535 FMT_EuphonyDriver::FMT_EuphonyDriver(Audio::Mixer *mixer)575 SoundTowns_EuphonyDriver::SoundTowns_EuphonyDriver(Audio::Mixer *mixer) 536 576 : MidiDriver_Emulated(mixer) { 537 577 538 578 _volume = 255; 539 _fadestate = 300; 579 _fadestate = EUPHONY_FADEOUT_TICKS; 580 _queue = 0; 540 581 541 582 MidiDriver_YM2612::createLookupTables(); 542 583 … … 551 592 552 593 rate(getRate()); 553 594 fading(0); 595 596 _queue = new SoundTowns_EuphonyTrackQueue(this, 0); 554 597 } 555 598 556 FMT_EuphonyDriver::~FMT_EuphonyDriver() {599 SoundTowns_EuphonyDriver::~SoundTowns_EuphonyDriver() { 557 600 for (int i = 0; i < 6; i++) 558 601 delete _fChannel[i]; 559 602 for (int i = 0; i < 8; i++) … … 577 620 _waveSounds[i] = 0; 578 621 } 579 622 } 623 624 if (_queue) { 625 _queue->release(); 626 delete _queue; 627 _queue = 0; 628 } 580 629 } 581 630 582 int FMT_EuphonyDriver::open() {631 int SoundTowns_EuphonyDriver::open() { 583 632 if (_isOpen) 584 633 return MERR_ALREADY_OPEN; 585 586 634 MidiDriver_Emulated::open(); 587 635 588 636 _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, 589 637 this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); 638 590 639 return 0; 591 640 } 592 641 593 void FMT_EuphonyDriver::close() {642 void SoundTowns_EuphonyDriver::close() { 594 643 if (!_isOpen) 595 644 return; 596 645 _isOpen = false; 597 646 _mixer->stopHandle(_mixerSoundHandle); 598 647 } 599 648 600 void FMT_EuphonyDriver::send(uint32 b) {649 void SoundTowns_EuphonyDriver::send(uint32 b) { 601 650 send(b & 0xF, b & 0xFFFFFFF0); 602 651 } 603 652 604 void FMT_EuphonyDriver::send(byte chan, uint32 b) { 605 //byte param3 = (byte) ((b >> 24) & 0xFF); 606 653 void SoundTowns_EuphonyDriver::send(byte chan, uint32 b) { 607 654 byte param2 = (byte) ((b >> 16) & 0xFF); 608 655 byte param1 = (byte) ((b >> 8) & 0xFF); 609 656 byte cmd = (byte) (b & 0xF0); … … 662 709 _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000); 663 710 break; 664 711 default: 665 warning(" FMT_EuphonyDriver: Unknown send() command 0x%02X", cmd);712 warning("SoundTowns_EuphonyDriver: Unknown send() command 0x%02X", cmd); 666 713 } 667 714 } 668 715 669 void FMT_EuphonyDriver::loadFmInstruments(const byte *instr) {716 void SoundTowns_EuphonyDriver::loadFmInstruments(const byte *instr) { 670 717 if (_fmInstruments) 671 718 delete [] _fmInstruments; 672 719 _fmInstruments = new uint8[0x1800]; 673 720 memcpy(_fmInstruments, instr, 0x1800); 674 721 } 675 722 676 void FMT_EuphonyDriver::loadWaveInstruments(const byte *instr) {723 void SoundTowns_EuphonyDriver::loadWaveInstruments(const byte *instr) { 677 724 if (_waveInstruments) 678 725 delete [] _waveInstruments; 679 726 _waveInstruments = new uint8[0x1000]; … … 698 745 } 699 746 700 747 701 void FMT_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) {748 void SoundTowns_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) { 702 749 _channel[midiChannelNumber] = _fChannel[fmChannelNumber]; 703 750 } 704 751 705 void FMT_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) {752 void SoundTowns_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) { 706 753 _channel[midiChannelNumber] = _wChannel[waveChannelNumber]; 707 754 } 708 755 709 void FMT_EuphonyDriver::removeChannel(uint8 midiChannelNumber) {756 void SoundTowns_EuphonyDriver::removeChannel(uint8 midiChannelNumber) { 710 757 _channel[midiChannelNumber] = 0; 711 758 } 712 759 713 void FMT_EuphonyDriver::generateSamples(int16 *data, int len) {760 void SoundTowns_EuphonyDriver::generateSamples(int16 *data, int len) { 714 761 memset(data, 0, 2 * sizeof(int16) * len); 715 762 nextTick(data, len); 716 763 } 717 764 718 void FMT_EuphonyDriver::nextTick(int16 *buf1, int buflen) {765 void SoundTowns_EuphonyDriver::nextTick(int16 *buf1, int buflen) { 719 766 int32 *buf0 = (int32 *)buf1; 720 767 721 768 for (int i = 0; i < ARRAYSIZE(_channel); i++) { … … 724 771 } 725 772 726 773 for (int i = 0; i < buflen; ++i) { 727 int s = int( float(buf0[i] * volume()) * float((float)_fadestate / 300) );774 int s = int( float(buf0[i] * _volume) * float((float)_fadestate / EUPHONY_FADEOUT_TICKS) ); 728 775 buf1[i*2] = buf1[i*2+1] = (s >> 9) & 0xffff; 729 776 } 730 777 731 778 if (_fading) { 732 if (_fadestate) 779 if (_fadestate) { 733 780 _fadestate--; 734 else781 } else { 735 782 _fading = false; 783 _queue->setPlayBackStatus(false); 784 } 736 785 } 737 786 } 738 787 739 void FMT_EuphonyDriver::rate(uint16 r) {788 void SoundTowns_EuphonyDriver::rate(uint16 r) { 740 789 for (uint8 i = 0; i < 16; i++) { 741 790 if (_channel[i]) 742 791 _channel[i]->rate(r); 743 792 } 744 793 } 745 794 746 void FMT_EuphonyDriver::fading(bool status) {795 void SoundTowns_EuphonyDriver::fading(bool status) { 747 796 _fading = status; 748 797 if (!_fading) 749 _fadestate = 300;798 _fadestate = EUPHONY_FADEOUT_TICKS; 750 799 } 751 800 752 MidiParser_EuD::MidiParser_EuD( ) : MidiParser(),801 MidiParser_EuD::MidiParser_EuD(SoundTowns_EuphonyTrackQueue * queue) : MidiParser(), 753 802 _firstBaseTickStep(0x33), _nextBaseTickStep(0x33) { 754 803 _initialTempo = calculateTempo(0x5a); 804 _queue = queue; 755 805 } 756 806 757 807 void MidiParser_EuD::parseNextEvent(EventInfo &info) { 758 808 byte *pos = _position._play_pos; 759 809 810 if (_queue->_next) { 811 if (info.ext.type == 0x2F) { 812 unloadMusic(); 813 memset(&info, 0, sizeof(EventInfo)); 814 pos = _position._play_pos = _tracks[0] = _queue->trackData() + 0x806; 815 } else if (_active_track == 255) { 816 _queue = _queue->_next; 817 setup(); 818 setTrack(0); 819 _queue->setPlayBackStatus(true); 820 return; 821 } else if (!_queue->isPlaying()) { 822 unloadMusic(); 823 _queue = _queue->_next; 824 setup(); 825 setTrack(0); 826 _queue->setPlayBackStatus(true); 827 return; 828 } 829 } 830 760 831 while (true) { 761 832 byte cmd = *pos; 762 833 byte evt = (cmd & 0xF0); … … 830 901 break; 831 902 } else if (cmd == 0xFD || cmd == 0xFE) { 832 903 // End of track. 833 if (_autoLoop) 904 if (_autoLoop) { 905 unloadMusic(); 906 _queue->setPlayBackStatus(true); 834 907 pos = info.start = _tracks[0]; 835 else908 } else { 836 909 info.start = pos; 910 } 837 911 838 912 uint32 last = _position._last_event_tick; 839 913 uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick; … … 852 926 _position._play_pos = pos; 853 927 } 854 928 855 bool MidiParser_EuD::loadMusic(byte *data, uint32 ) {856 unloadMusic();929 bool MidiParser_EuD::loadMusic(byte *data, uint32 size) { 930 bool loop = _autoLoop; 857 931 858 _enable = data + 0x354; 859 _mode = data + 0x374; 860 _channel = data + 0x394; 861 _adjVelo = data + 0x3B4; 862 _adjNote = (int8*) data + 0x3D4; 863 864 _firstBaseTickStep = data[0x804]; 865 _initialTempo = calculateTempo((data[0x805] > 0xfc) ? 0x5a : data[0x805]); 866 867 _num_tracks = 1; 868 _ppqn = 120; 869 _tracks[0] = data + 0x806; 870 871 resetTracking(); 872 setTrack (0); 873 932 if (_queue->isPlaying() && !_queue->_loop) { 933 _queue->loadDataToEndOfQueue(data, size, loop); 934 } else { 935 unloadMusic(); 936 _queue = _queue->reset(); 937 _queue->release(); 938 _queue->loadDataToCurrentPosition(data, size, loop); 939 setup(); 940 setTrack(0); 941 _queue->setPlayBackStatus(true); 942 } 874 943 return true; 875 944 } 876 945 … … 892 961 893 962 void MidiParser_EuD::resetTracking() { 894 963 MidiParser::resetTracking(); 964 895 965 _nextBaseTickStep = _firstBaseTickStep; 896 966 _baseTick = 0; 897 967 setTempo(_initialTempo); 968 _queue->setPlayBackStatus(false); 898 969 } 899 970 971 void MidiParser_EuD::setup() { 972 uint8 *data = _queue->trackData(); 973 if (!data) 974 return; 975 _queue->initDriver(); 976 977 _enable = data + 0x354; 978 _mode = data + 0x374; 979 _channel = data + 0x394; 980 _adjVelo = data + 0x3B4; 981 _adjNote = (int8*) data + 0x3D4; 982 983 _nextBaseTickStep = _firstBaseTickStep = data[0x804]; 984 _initialTempo = calculateTempo((data[0x805] > 0xfc) ? 0x5a : data[0x805]); 985 986 property(MidiParser::mpAutoLoop, _queue->_loop); 987 988 _num_tracks = 1; 989 _ppqn = 120; 990 _tracks[0] = data + 0x806; 991 } 992 993 SoundTowns_EuphonyTrackQueue::SoundTowns_EuphonyTrackQueue(SoundTowns_EuphonyDriver * driver, SoundTowns_EuphonyTrackQueue * last) { 994 _trackData = 0; 995 _next = 0; 996 _driver = driver; 997 _last = last; 998 _used = _fchan = _wchan = 0; 999 _playing = false; 1000 } 1001 1002 void SoundTowns_EuphonyTrackQueue::setPlayBackStatus(bool playing) { 1003 SoundTowns_EuphonyTrackQueue * i = this; 1004 do { 1005 i->_playing = playing; 1006 i = i->_next; 1007 } while (i); 1008 } 1009 1010 SoundTowns_EuphonyTrackQueue * SoundTowns_EuphonyTrackQueue::reset() { 1011 SoundTowns_EuphonyTrackQueue * i = this; 1012 while (i->_last) 1013 i = i->_last; 1014 return i; 1015 } 1016 1017 void SoundTowns_EuphonyTrackQueue::loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop) { 1018 if (_trackData) 1019 delete [] _trackData; 1020 _trackData = new uint8[0xC58A]; 1021 memset(_trackData, 0, 0xC58A); 1022 Screen::decodeFrame4(trackdata, _trackData, size); 1023 1024 _used = _trackData + 0x374; 1025 _fchan = _trackData + 0x6d4; 1026 _wchan = _trackData + 0x6dA; 1027 _loop = loop; 1028 _playing = false; 1029 } 1030 1031 void SoundTowns_EuphonyTrackQueue::loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop) { 1032 if (!_trackData) { 1033 loadDataToCurrentPosition(trackdata, size, loop); 1034 return; 1035 } 1036 1037 SoundTowns_EuphonyTrackQueue * i = this; 1038 while (i->_next) 1039 i = i->_next; 1040 1041 i = i->_next = new SoundTowns_EuphonyTrackQueue(_driver, i); 1042 i->_trackData = new uint8[0xC58A]; 1043 memset(i->_trackData, 0, 0xC58A); 1044 Screen::decodeFrame4(trackdata, i->_trackData, size); 1045 1046 i->_used = i->_trackData + 0x374; 1047 i->_fchan = i->_trackData + 0x6d4; 1048 i->_wchan = i->_trackData + 0x6dA; 1049 i->_loop = loop; 1050 i->_playing = _playing; 1051 } 1052 1053 void SoundTowns_EuphonyTrackQueue::release() { 1054 SoundTowns_EuphonyTrackQueue * i = _next; 1055 _next = 0; 1056 _playing = false; 1057 _used = _fchan = _wchan = 0; 1058 1059 if (_trackData) { 1060 delete [] _trackData; 1061 _trackData = 0; 1062 } 1063 1064 while (i) { 1065 if (i->_trackData) { 1066 delete [] i->_trackData; 1067 i->_trackData = 0; 1068 } 1069 i = i->_next; 1070 if (i) 1071 delete i->_last; 1072 } 1073 } 1074 1075 void SoundTowns_EuphonyTrackQueue::initDriver() { 1076 for (uint8 i = 0; i < 6; i++) { 1077 if (_used[_fchan[i]]) 1078 _driver->assignFmChannel(_fchan[i], i); 1079 } 1080 1081 for (uint8 i = 0; i < 8; i++) { 1082 if (_used[_wchan[i]]) 1083 _driver->assignWaveChannel(_wchan[i], i); 1084 } 1085 1086 for (uint8 i = 0; i < 16; i++) { 1087 if (!_used[i]) 1088 _driver->removeChannel(i); 1089 } 1090 _driver->send(0x79B0); 1091 } 1092 900 1093 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) {1094 _currentSFX(0), _sfxFileData(0), _sfxFileIndex((uint)-1), _sfxWDTable(0), _parser(0), _sfxVolume(255) { 902 1095 903 _driver = new FMT_EuphonyDriver(_mixer);1096 _driver = new SoundTowns_EuphonyDriver(_mixer); 904 1097 int ret = open(); 905 1098 if (ret != MERR_ALREADY_OPEN && ret != 0) { 906 1099 error("couldn't open midi driver"); … … 916 1109 _driver->setTimerCallback(0, 0); 917 1110 close(); 918 1111 919 if (_musicTrackData)920 delete [] _musicTrackData;921 922 1112 _driver = 0; 923 1113 } 924 1114 … … 950 1140 track -= 2; 951 1141 952 1142 static const CDTrackTable tTable[] = { 953 { 0x04000, 1, 0 }, 954 { 0x05480, 1, 6 }, 955 { 0x05E70, 0, 1 }, 956 { 0x06D90, 1, 3 }, 957 { 0x072C0, 0, -1 }, 958 { 0x075F0, 1, -1 }, 959 { 0x07880, 1, -1 }, 960 { 0x089C0, 0, -1 }, 961 { 0x09080, 0, -1 }, 962 { 0x091D0, 1, 4 }, 963 { 0x0A880, 1, 5 }, 964 { 0x0AF50, 0, -1 }, 965 { 0x0B1A0, 1, -1 }, 966 { 0x0B870, 0, -1 }, 967 { 0x0BCF0, 1, -1 }, 968 { 0x0C5D0, 1, 7 }, 969 { 0x0D3E0, 1, 8 }, 970 { 0x0e7b0, 1, 2 }, 971 { 0x0edc0, 0, -1 }, 972 { 0x0eef0, 1, 9 }, 973 { 0x10540, 1, 10 }, 974 { 0x10d80, 0, -1 }, 975 { 0x10E30, 0, -1 }, 976 { 0x10FC0, 0, -1 }, 977 { 0x11310, 1, -1 }, 978 { 0x11A20, 1, -1 }, 979 { 0x12380, 0, -1 }, 980 { 0x12540, 1, -1 }, 981 { 0x12730, 1, -1 }, 982 { 0x12A90, 1, 11 }, 983 { 0x134D0, 0, -1 }, 984 { 0x00000, 0, -1 }, 985 { 0x13770, 0, -1 }, 986 { 0x00000, 0, -1 }, 987 { 0x00000, 0, -1 }, 988 { 0x00000, 0, -1 }, 989 { 0x00000, 0, -1 }, 990 { 0x14710, 1, 12 }, 991 { 0x15DF0, 1, 13 }, 992 { 0x16030, 1, 14 }, 993 { 0x17030, 0, -1 }, 994 { 0x17650, 0, -1 }, 995 { 0x134D0, 0, -1 }, 996 { 0x178E0, 1, -1 }, 997 { 0x18200, 0, -1 }, 998 { 0x18320, 0, -1 }, 999 { 0x184A0, 0, -1 }, 1000 { 0x18BB0, 0, -1 }, 1001 { 0x19040, 0, 19 }, 1002 { 0x19B50, 0, 20 }, 1003 { 0x17650, 0, -1 }, 1004 { 0x1A730, 1, 21 }, 1005 { 0x00000, 0, -1 }, 1006 { 0x12380, 0, -1 }, 1007 { 0x1B810, 0, -1 }, 1008 { 0x1BA50, 0, 15 }, 1009 { 0x1C190, 0, 16 }, 1010 { 0x1CA50, 0, 17 }, 1011 { 0x1D100, 0, 18 }, 1143 { 0x04000, 1, 0 }, { 0x05480, 1, 6 }, { 0x05E70, 0, 1 }, 1144 { 0x06D90, 1, 3 }, { 0x072C0, 0, -1 }, { 0x075F0, 1, -1 }, 1145 { 0x07880, 1, -1 }, { 0x089C0, 0, -1 }, { 0x09080, 0, -1 }, 1146 { 0x091D0, 1, 4 }, { 0x0A880, 1, 5 }, { 0x0AF50, 0, -1 }, 1147 { 0x0B1A0, 1, -1 }, { 0x0B870, 0, -1 }, { 0x0BCF0, 1, -1 }, 1148 { 0x0C5D0, 1, 7 }, { 0x0D3E0, 1, 8 }, { 0x0e7b0, 1, 2 }, 1149 { 0x0edc0, 0, -1 }, { 0x0eef0, 1, 9 }, { 0x10540, 1, 10 }, 1150 { 0x10d80, 0, -1 }, { 0x10E30, 0, -1 }, { 0x10FC0, 0, -1 }, 1151 { 0x11310, 1, -1 }, { 0x11A20, 1, -1 }, { 0x12380, 0, -1 }, 1152 { 0x12540, 1, -1 }, { 0x12730, 1, -1 }, { 0x12A90, 1, 11 }, 1153 { 0x134D0, 0, -1 }, { 0x00000, 0, -1 }, { 0x13770, 0, -1 }, 1154 { 0x00000, 0, -1 }, { 0x00000, 0, -1 }, { 0x00000, 0, -1 }, 1155 { 0x00000, 0, -1 }, { 0x14710, 1, 12 }, { 0x15DF0, 1, 13 }, 1156 { 0x16030, 1, 14 }, { 0x17030, 0, -1 }, { 0x17650, 0, -1 }, 1157 { 0x134D0, 0, -1 }, { 0x178E0, 1, -1 }, { 0x18200, 0, -1 }, 1158 { 0x18320, 0, -1 }, { 0x184A0, 0, -1 }, { 0x18BB0, 0, -1 }, 1159 { 0x19040, 0, 19 }, { 0x19B50, 0, 20 }, { 0x17650, 0, -1 }, 1160 { 0x1A730, 1, 21 }, { 0x00000, 0, -1 }, { 0x12380, 0, -1 }, 1161 { 0x1B810, 0, -1 }, { 0x1BA50, 0, 15 }, { 0x1C190, 0, 16 }, 1162 { 0x1CA50, 0, 17 }, { 0x1D100, 0, 18 } 1012 1163 }; 1013 1164 1014 1165 int trackNum = tTable[track].track; … … 1017 1168 if (track == _lastTrack && _musicEnabled) 1018 1169 return; 1019 1170 1020 haltTrack();1171 beginFadeOut(); 1021 1172 1022 1173 if (_musicEnabled == 2 && trackNum != -1) { 1023 1174 AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0); … … 1035 1186 AudioCD.updateCD(); 1036 1187 if (_parser) { 1037 1188 Common::StackLock lock(_mutex); 1038 1039 1189 _parser->setTrack(0); 1040 1190 _parser->jumpToTick(0); 1041 1042 1191 _parser->unloadMusic(); 1043 1192 delete _parser; 1044 1193 _parser = 0; 1045 1046 1194 setVolume(255); 1047 1195 } 1196 _driver->queue()->release(); 1048 1197 } 1049 1198 1199 void SoundTowns::setMusicVolume(int volume) { 1200 _driver->setVolume(volume); 1201 } 1202 1050 1203 void SoundTowns::loadSoundFile(uint file) { 1051 1204 if (_sfxFileIndex == file) 1052 1205 return; … … 1143 1296 1144 1297 _currentSFX = Audio::makeLinearInputStream(sfxPlaybackBuffer, playbackBufferSize, 1145 1298 outputRate, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0); 1146 _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX );1299 _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX, -1, _sfxVolume); 1147 1300 } 1148 1301 1149 1302 void SoundTowns::beginFadeOut() { … … 1181 1334 } 1182 1335 1183 1336 bool SoundTowns::loadInstruments() { 1184 if (!_musicTrackData)1185 _musicTrackData = new uint8[0xC58A];1186 1187 memset(_musicTrackData, 0, 0xC58A);1188 1337 uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0); 1189 1338 if (!twm) 1190 1339 return false; 1191 Screen::decodeFrame4(twm, _musicTrackData, 0x8BF0);1192 _driver->loadFmInstruments(_ musicTrackData+ 8);1340 _driver->queue()->loadDataToCurrentPosition(twm, 0x8BF0); 1341 _driver->loadFmInstruments(_driver->queue()->trackData() + 8); 1193 1342 1194 memset (_musicTrackData,0, 0xC58A);1195 Screen::decodeFrame4(twm + 0x0CA0, _musicTrackData, 0xC58A);1343 _driver->queue()->loadDataToCurrentPosition(twm + 0x0CA0, 0xC58A); 1344 _driver->loadWaveInstruments(_driver->queue()->trackData() + 8); 1196 1345 delete [] twm; 1197 _driver-> loadWaveInstruments(_musicTrackData + 8);1346 _driver->queue()->release(); 1198 1347 1199 1348 return true; 1200 1349 } 1201 1350 1202 1351 void SoundTowns::playEuphonyTrack(uint32 offset, int loop) { 1203 if (!_musicTrackData)1204 _musicTrackData = new uint8[0xC58A];1205 1206 memset(_musicTrackData, 0, 0xC58A);1207 1352 uint8 * twm = _vm->resource()->fileData("twmusic.pak", 0); 1208 Screen::decodeFrame4(twm + 0x4b70 + offset, _musicTrackData, 0xC58A);1209 delete [] twm;1210 1353 1211 Common::StackLock lock(_mutex); 1212 1213 uint8 * used = _musicTrackData + 0x374; 1214 uint8 * fchan = _musicTrackData + 0x6d4; 1215 uint8 * wchan = _musicTrackData + 0x6dA; 1216 1217 for (uint8 i = 0; i < 6; i++) { 1218 if (used[fchan[i]]) 1219 _driver->assignFmChannel(fchan[i], i); 1354 if (!_parser) { 1355 _parser = new MidiParser_EuD(_driver->queue()); 1356 _parser->setMidiDriver(this); 1357 _parser->setTimerRate(getBaseTempo()); 1220 1358 } 1221 1359 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 1360 _parser->property(MidiParser::mpAutoLoop, loop); 1238 _parser->loadMusic(_musicTrackData, 0); 1239 _parser->jumpToTick(0); 1361 _parser->loadMusic(twm + 0x4b70 + offset, 0xC58A); 1240 1362 1241 _parser->setMidiDriver(this); 1242 _parser->setTimerRate(getBaseTempo()); 1363 delete [] twm; 1243 1364 } 1244 1365 1245 1366 void SoundTowns::onTimer(void * data) { … … 1302 1423 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 1303 1424 }; 1304 1425 1426 // KYRA 2 1427 1428 SoundTowns_v2::SoundTowns_v2(KyraEngine *vm, Audio::Mixer *mixer) : 1429 Sound(vm, mixer), _lastTrack(-1), _currentSFX(0), /*_driver(0),*/ 1430 _twnTrackData(0), _sfxVolume(255) { 1431 } 1432 1433 SoundTowns_v2::~SoundTowns_v2() { 1434 /*if (_driver) 1435 delete _driver;*/ 1436 if (_twnTrackData) 1437 delete [] _twnTrackData; 1438 } 1439 1440 bool SoundTowns_v2::init() { 1441 //_driver = new SoundTowns_v2_TwnDriver(_mixer); 1442 _vm->checkCD(); 1443 Common::File f; 1444 if (_musicEnabled && (f.exists("track1.mp3") || 1445 f.exists("track1.ogg") || f.exists("track1.flac") || f.exists("track1.fla"))) 1446 _musicEnabled = 2; 1447 return true;//_driver->init(); 1448 } 1449 1450 void SoundTowns_v2::process() { 1451 AudioCD.updateCD(); 1452 } 1453 1454 void SoundTowns_v2::setMusicVolume(int volume) { 1455 /* TODO */ 1456 } 1457 1458 void SoundTowns_v2::playTrack(uint8 track) { 1459 if (track == _lastTrack && _musicEnabled) 1460 return; 1461 1462 int trackNum = -1; 1463 for (int i = 0; i < _themes[_currentTheme].cdaTableSize; i++) { 1464 if (track == _themes[_currentTheme].cdaTable[i * 2]) { 1465 trackNum = _themes[_currentTheme].cdaTable[i * 2 + 1] - 1; 1466 break; 1467 } 1468 } 1469 1470 haltTrack(); 1471 1472 // TODO: figure out when to loop and when not for CD Audio 1473 bool loop = false; 1474 1475 if (_musicEnabled == 2 && trackNum != -1) { 1476 AudioCD.play(trackNum+1, loop ? -1 : 1, 0, 0); 1477 AudioCD.updateCD(); 1478 } else if (_musicEnabled) { 1479 char musicfile[13]; 1480 sprintf(musicfile, "%s%d.twn", _themes[_currentTheme].twnFilename, track); 1481 if (_twnTrackData) 1482 delete [] _twnTrackData; 1483 _twnTrackData = _vm->resource()->fileData(musicfile, 0); 1484 //_driver->loadData(_twnTrackData); 1485 } 1486 1487 _lastTrack = track; 1488 } 1489 1490 void SoundTowns_v2::haltTrack() { 1491 _lastTrack = -1; 1492 AudioCD.stop(); 1493 AudioCD.updateCD(); 1494 //_driver->reset(); 1495 } 1496 1497 void SoundTowns_v2::voicePlay(const char *file) { 1498 static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 }; 1499 1500 uint8 * data = _vm->resource()->fileData(file, 0); 1501 uint8 * src = data; 1502 1503 uint16 sfxRate = rates[READ_LE_UINT16(src)]; 1504 src += 2; 1505 bool compressed = (READ_LE_UINT16(src) & 1) ? true : false; 1506 src += 2; 1507 uint32 outsize = READ_LE_UINT32(src); 1508 uint8 *sfx = (uint8*) malloc(outsize); 1509 uint8 *dst = sfx; 1510 src += 4; 1511 1512 if (compressed) { 1513 for (uint32 i = outsize; i;) { 1514 uint8 cnt = *src++; 1515 if (cnt & 0x80) { 1516 cnt &= 0x7F; 1517 memset(dst, *src++, cnt); 1518 } else { 1519 memcpy(dst, src, cnt); 1520 src += cnt; 1521 } 1522 dst += cnt; 1523 i -= cnt; 1524 } 1525 } else { 1526 memcpy(dst, src, outsize); 1527 } 1528 1529 for (uint32 i = 0; i < outsize; i++) { 1530 uint8 cmd = sfx[i]; 1531 if (cmd & 0x80) { 1532 cmd = ~cmd; 1533 } else { 1534 cmd |= 0x80; 1535 if (cmd == 0xff) 1536 cmd--; 1537 } 1538 if (cmd < 0x80) 1539 cmd = 0x80 - cmd; 1540 sfx[i] = cmd; 1541 } 1542 1543 uint32 outputRate = uint32(11025 * SoundTowns::semitoneAndSampleRate_to_sampleStep(0x3c, 0x3c, sfxRate, 11025, 0x2000)); 1544 1545 _currentSFX = Audio::makeLinearInputStream(sfx, outsize, outputRate, 1546 Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0); 1547 _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX, -1, _sfxVolume); 1548 1549 delete [] data; 1550 } 1551 1552 void SoundTowns_v2::beginFadeOut() { 1553 //_driver->fadeOut(); 1554 haltTrack(); 1555 } 1556 1557 const uint8 SoundTowns_v2::_cdaTrackTableK2Intro[] = { 1558 0x03, 0x01, 0x04, 0x02, 0x05, 0x03, 0x06, 0x04, 0x07, 0x05, 0x08, 0x06 1559 }; 1560 1561 const uint8 SoundTowns_v2::_cdaTrackTableK2Ingame[] = { 1562 0x02, 0x07, 0x03, 0x08, 0x04, 0x09, 0x07, 0x0A, 0x0C, 0x0B, 0x0D, 0x0C, 0x0E, 0x0D, 0x0F, 0x0E, 1563 0x10, 0x0F, 0x12, 0x10, 0x13, 0x11, 0x15, 0x12, 0x17, 0x13, 0x18, 0x14, 0x19, 0x15, 0x1A, 0x16, 1564 0x1B, 0x17, 0x1C, 0x18, 0x1D, 0x19, 0x1E, 0x1A, 0x1F, 0x1B, 0x21, 0x1C, 0x22, 0x1D, 0x23, 0x1E, 1565 0x24, 0x1F, 0x25, 0x20, 0x26, 0x21, 0x27, 0x22, 0x28, 0x23, 0x29, 0x24, 0x2A, 0x25, 0x2B, 0x26, 1566 0x2C, 0x27, 0x2D, 0x28, 0x2E, 0x29, 0x2F, 0x2A, 0x30, 0x2B, 0x31, 0x2C, 0x32, 0x2D, 0x33, 0x2E, 1567 0x34, 0x2F, 0x35, 0x30, 0x36, 0x31, 0x37, 0x32, 0x38, 0x33, 0x39, 0x34, 0x3A, 0x35, 0x3B, 0x36, 1568 0x3C, 0x37, 0x3D, 0x38, 0x3E, 0x39, 0x3F, 0x3A, 0x40, 0x3B, 0x41, 0x3C, 0x42, 0x3D, 0x43, 0x3E, 1569 0x44, 0x3F, 0x45, 0x40, 0x46, 0x41, 0x47, 0x42, 0x48, 0x43, 0x49, 0x44, 0x4A, 0x45, 0x4B, 0x46, 1570 0x4C, 0x47, 0x4D, 0x48, 0x4E, 0x49, 0x4F, 0x4A, 0x50, 0x4B, 0x51, 0x4C, 0x52, 0x4D, 0x53, 0x4E, 1571 0x54, 0x4F, 0x55, 0x50, 0x56, 0x51, 0x57, 0x52 1572 }; 1573 1574 const uint8 SoundTowns_v2::_cdaTrackTableK2Finale[] = { 1575 0x03, 0x53, 0x04, 0x54 1576 }; 1577 1578 const Kyra2AudioThemes SoundTowns_v2::_themes[] = { 1579 { _cdaTrackTableK2Intro, ARRAYSIZE(_cdaTrackTableK2Intro) >> 1, "intro" }, 1580 { _cdaTrackTableK2Ingame, ARRAYSIZE(_cdaTrackTableK2Ingame) >> 1, "k2" }, 1581 { _cdaTrackTableK2Finale, ARRAYSIZE(_cdaTrackTableK2Finale) >> 1, "finale" } 1582 }; 1583 1305 1584 } // end of namespace Kyra 1306 1585 1586 #undef EUPHONY_FADEOUT_TICKS 1587 1588 #if _MSC_VER >= 1400 1589 #undef sprintf 1590 #endif 1591 No newline at end of file