PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/engines/scumm/players/player_nes.cpp

http://github.com/scummvm/scummvm
C++ | 1077 lines | 849 code | 200 blank | 28 comment | 116 complexity | 3f1c827a4088e9e5fe7ffe0f96ca8a5d MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, GPL-2.0
  1. /* ScummVM - Graphic Adventure Engine
  2. *
  3. * ScummVM is the legal property of its developers, whose names
  4. * are too numerous to list here. Please refer to the COPYRIGHT
  5. * file distributed with this source distribution.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20. *
  21. */
  22. #ifndef DISABLE_NES_APU
  23. #include "engines/engine.h"
  24. #include "scumm/players/player_nes.h"
  25. #include "scumm/scumm.h"
  26. #include "audio/mixer.h"
  27. namespace Scumm {
  28. static const byte channelMask[4] = {1, 2, 4, 8};
  29. static const uint16 freqTable[64] = {
  30. 0x07F0, 0x077E, 0x0712, 0x06AE, 0x064E, 0x05F3, 0x059E, 0x054D,
  31. 0x0501, 0x04B9, 0x0475, 0x0435, 0x03F8, 0x03BF, 0x0389, 0x0357,
  32. 0x0327, 0x02F9, 0x02CF, 0x02A6, 0x0280, 0x025C, 0x023A, 0x021A,
  33. 0x01FC, 0x01DF, 0x01C4, 0x01AB, 0x0193, 0x017C, 0x0167, 0x0152,
  34. 0x013F, 0x012D, 0x011C, 0x010C, 0x00FD, 0x00EE, 0x00E1, 0x00D4,
  35. 0x00C8, 0x00BD, 0x00B2, 0x00A8, 0x009F, 0x0096, 0x008D, 0x0085,
  36. 0x007E, 0x0076, 0x0070, 0x0069, 0x0063, 0x005E, 0x0058, 0x0053,
  37. 0x004F, 0x004A, 0x0046, 0x0042, 0x003E, 0x003A, 0x0037, 0x0034
  38. };
  39. static const byte instChannel[16] = {
  40. 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 1, 3, 3, 3
  41. };
  42. static const byte startCmd[16] = {
  43. 0x05, 0x03, 0x06, 0x08, 0x0B, 0x01, 0x01, 0x1A,
  44. 0x16, 0x06, 0x04, 0x17, 0x02, 0x10, 0x0E, 0x0D
  45. };
  46. static const byte releaseCmd[16] = {
  47. 0x0F, 0x00, 0x00, 0x09, 0x00, 0x14, 0x15, 0x00,
  48. 0x00, 0x00, 0x1B, 0x1B, 0x0F, 0x0F, 0x0F, 0x0F
  49. };
  50. static const byte nextCmd[28] = {
  51. 0xFF, 0xFF, 0xFF, 0xFF, 0x17, 0xFF, 0x07, 0xFF,
  52. 0xFF, 0x0A, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00,
  53. 0x11, 0x12, 0x11, 0x03, 0xFF, 0xFF, 0x18, 0x00,
  54. 0x19, 0x00, 0x00, 0x00
  55. };
  56. static const byte nextDelay[28] = {
  57. 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
  58. 0x00, 0x05, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00,
  59. 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00,
  60. 0x03, 0x00, 0x00, 0x00
  61. };
  62. namespace APUe {
  63. static const byte LengthCounts[32] = {
  64. 0x0A,0xFE,
  65. 0x14,0x02,
  66. 0x28,0x04,
  67. 0x50,0x06,
  68. 0xA0,0x08,
  69. 0x3C,0x0A,
  70. 0x0E,0x0C,
  71. 0x1A,0x0E,
  72. 0x0C,0x10,
  73. 0x18,0x12,
  74. 0x30,0x14,
  75. 0x60,0x16,
  76. 0xC0,0x18,
  77. 0x48,0x1A,
  78. 0x10,0x1C,
  79. 0x20,0x1E
  80. };
  81. class SoundGen {
  82. protected:
  83. byte wavehold;
  84. uint32 freq; // short
  85. uint32 CurD;
  86. public:
  87. byte Timer;
  88. int32 Pos;
  89. uint32 Cycles; // short
  90. inline byte GetTimer() const { return Timer; }
  91. };
  92. class Square : public SoundGen {
  93. protected:
  94. byte volume, envelope, duty, swpspeed, swpdir, swpstep, swpenab;
  95. byte Vol;
  96. byte EnvCtr, Envelope, BendCtr;
  97. bool Enabled, ValidFreq, Active;
  98. bool EnvClk, SwpClk;
  99. void CheckActive();
  100. public:
  101. void Reset();
  102. void Write(int Reg, byte Val);
  103. void Run();
  104. void QuarterFrame();
  105. void HalfFrame();
  106. };
  107. static const int8 Duties[4][8] = {
  108. {-4,+4,-4,-4,-4,-4,-4,-4},
  109. {-4,+4,+4,-4,-4,-4,-4,-4},
  110. {-4,+4,+4,+4,+4,-4,-4,-4},
  111. {+4,-4,-4,+4,+4,+4,+4,+4}
  112. };
  113. void Square::Reset() {
  114. memset(this, 0, sizeof(*this));
  115. Cycles = 1;
  116. EnvCtr = 1;
  117. BendCtr = 1;
  118. }
  119. void Square::CheckActive() {
  120. ValidFreq = (freq >= 0x8) && ((swpdir) || !((freq + (freq >> swpstep)) & 0x800));
  121. Active = Timer && ValidFreq;
  122. Pos = Active ? (Duties[duty][CurD] * Vol) : 0;
  123. }
  124. void Square::Write(int Reg, byte Val) {
  125. switch (Reg) {
  126. case 0:
  127. volume = Val & 0xF;
  128. envelope = Val & 0x10;
  129. wavehold = Val & 0x20;
  130. duty = (Val >> 6) & 0x3;
  131. Vol = envelope ? volume : Envelope;
  132. break;
  133. case 1:
  134. swpstep = Val & 0x07;
  135. swpdir = Val & 0x08;
  136. swpspeed = (Val >> 4) & 0x7;
  137. swpenab = Val & 0x80;
  138. SwpClk = true;
  139. break;
  140. case 2:
  141. freq &= 0x700;
  142. freq |= Val;
  143. break;
  144. case 3:
  145. freq &= 0xFF;
  146. freq |= (Val & 0x7) << 8;
  147. if (Enabled)
  148. Timer = LengthCounts[(Val >> 3) & 0x1F];
  149. CurD = 0;
  150. EnvClk = true;
  151. break;
  152. case 4:
  153. Enabled = (Val != 0);
  154. if (!Enabled)
  155. Timer = 0;
  156. break;
  157. default:
  158. break;
  159. }
  160. CheckActive();
  161. }
  162. void Square::Run() {
  163. Cycles = (freq + 1) << 1;
  164. CurD = (CurD + 1) & 0x7;
  165. if (Active)
  166. Pos = Duties[duty][CurD] * Vol;
  167. }
  168. void Square::QuarterFrame() {
  169. if (EnvClk) {
  170. EnvClk = false;
  171. Envelope = 0xF;
  172. EnvCtr = volume + 1;
  173. } else if (!--EnvCtr) {
  174. EnvCtr = volume + 1;
  175. if (Envelope)
  176. Envelope--;
  177. else
  178. Envelope = wavehold ? 0xF : 0x0;
  179. }
  180. Vol = envelope ? volume : Envelope;
  181. CheckActive();
  182. }
  183. void Square::HalfFrame() {
  184. if (!--BendCtr) {
  185. BendCtr = swpspeed + 1;
  186. if (swpenab && swpstep && ValidFreq) {
  187. int sweep = freq >> swpstep;
  188. // FIXME: Is -sweep or ~sweep correct???
  189. freq += swpdir ? -sweep : sweep;
  190. }
  191. }
  192. if (SwpClk) {
  193. SwpClk = false;
  194. BendCtr = swpspeed + 1;
  195. }
  196. if (Timer && !wavehold)
  197. Timer--;
  198. CheckActive();
  199. }
  200. class Triangle : public SoundGen {
  201. protected:
  202. byte linear;
  203. byte LinCtr;
  204. bool Enabled, Active;
  205. bool LinClk;
  206. void CheckActive();
  207. public:
  208. void Reset();
  209. void Write(int Reg, byte Val);
  210. void Run();
  211. void QuarterFrame();
  212. void HalfFrame();
  213. };
  214. static const int8 TriDuty[32] = {
  215. -8,-7,-6,-5,-4,-3,-2,-1,
  216. +0,+1,+2,+3,+4,+5,+6,+7,
  217. +7,+6,+5,+4,+3,+2,+1,+0,
  218. -1,-2,-3,-4,-5,-6,-7,-8
  219. };
  220. void Triangle::Reset() {
  221. memset(this, 0, sizeof(*this));
  222. Cycles = 1;
  223. }
  224. void Triangle::CheckActive() {
  225. Active = Timer && LinCtr;
  226. if (freq < 4)
  227. Pos = 0; // beyond hearing range
  228. else
  229. Pos = TriDuty[CurD] * 8;
  230. }
  231. void Triangle::Write(int Reg, byte Val) {
  232. switch (Reg) {
  233. case 0:
  234. linear = Val & 0x7F;
  235. wavehold = (Val >> 7) & 0x1;
  236. break;
  237. case 2:
  238. freq &= 0x700;
  239. freq |= Val;
  240. break;
  241. case 3:
  242. freq &= 0xFF;
  243. freq |= (Val & 0x7) << 8;
  244. if (Enabled)
  245. Timer = LengthCounts[(Val >> 3) & 0x1F];
  246. LinClk = true;
  247. break;
  248. case 4:
  249. Enabled = (Val != 0);
  250. if (!Enabled)
  251. Timer = 0;
  252. break;
  253. default:
  254. break;
  255. }
  256. CheckActive();
  257. }
  258. void Triangle::Run() {
  259. Cycles = freq + 1;
  260. if (Active) {
  261. CurD++;
  262. CurD &= 0x1F;
  263. if (freq < 4)
  264. Pos = 0; // beyond hearing range
  265. else
  266. Pos = TriDuty[CurD] * 8;
  267. }
  268. }
  269. void Triangle::QuarterFrame() {
  270. if (LinClk)
  271. LinCtr = linear;
  272. else if (LinCtr)
  273. LinCtr--;
  274. if (!wavehold)
  275. LinClk = false;
  276. CheckActive();
  277. }
  278. void Triangle::HalfFrame() {
  279. if (Timer && !wavehold)
  280. Timer--;
  281. CheckActive();
  282. }
  283. class Noise : public SoundGen {
  284. protected:
  285. byte volume, envelope, datatype;
  286. byte Vol;
  287. byte EnvCtr, Envelope;
  288. bool Enabled;
  289. bool EnvClk;
  290. void CheckActive();
  291. public:
  292. void Reset();
  293. void Write(int Reg, byte Val);
  294. void Run();
  295. void QuarterFrame();
  296. void HalfFrame();
  297. };
  298. static const uint32 NoiseFreq[16] = {
  299. 0x004,0x008,0x010,0x020,0x040,0x060,0x080,0x0A0,
  300. 0x0CA,0x0FE,0x17C,0x1FC,0x2FA,0x3F8,0x7F2,0xFE4
  301. };
  302. void Noise::Reset() {
  303. memset(this, 0, sizeof(*this));
  304. CurD = 1;
  305. Cycles = 1;
  306. EnvCtr = 1;
  307. }
  308. void Noise::Write(int Reg, byte Val) {
  309. switch (Reg) {
  310. case 0:
  311. volume = Val & 0x0F;
  312. envelope = Val & 0x10;
  313. wavehold = Val & 0x20;
  314. Vol = envelope ? volume : Envelope;
  315. if (Timer)
  316. Pos = ((CurD & 0x4000) ? -2 : 2) * Vol;
  317. break;
  318. case 2:
  319. freq = Val & 0xF;
  320. datatype = Val & 0x80;
  321. break;
  322. case 3:
  323. if (Enabled)
  324. Timer = LengthCounts[(Val >> 3) & 0x1F];
  325. EnvClk = true;
  326. break;
  327. case 4:
  328. Enabled = (Val != 0);
  329. if (!Enabled)
  330. Timer = 0;
  331. break;
  332. default:
  333. break;
  334. }
  335. }
  336. void Noise::Run() {
  337. Cycles = NoiseFreq[freq]; /* no + 1 here */
  338. if (datatype)
  339. CurD = (CurD << 1) | (((CurD >> 14) ^ (CurD >> 8)) & 0x1);
  340. else
  341. CurD = (CurD << 1) | (((CurD >> 14) ^ (CurD >> 13)) & 0x1);
  342. if (Timer)
  343. Pos = ((CurD & 0x4000) ? -2 : 2) * Vol;
  344. }
  345. void Noise::QuarterFrame() {
  346. if (EnvClk) {
  347. EnvClk = false;
  348. Envelope = 0xF;
  349. EnvCtr = volume + 1;
  350. } else if (!--EnvCtr) {
  351. EnvCtr = volume + 1;
  352. if (Envelope)
  353. Envelope--;
  354. else
  355. Envelope = wavehold ? 0xF : 0x0;
  356. }
  357. Vol = envelope ? volume : Envelope;
  358. if (Timer)
  359. Pos = ((CurD & 0x4000) ? -2 : 2) * Vol;
  360. }
  361. void Noise::HalfFrame() {
  362. if (Timer && !wavehold)
  363. Timer--;
  364. }
  365. class APU {
  366. protected:
  367. int BufPos;
  368. int SampleRate;
  369. Square _square0;
  370. Square _square1;
  371. Triangle _triangle;
  372. Noise _noise;
  373. struct {
  374. uint32 Cycles;
  375. int Num;
  376. } Frame;
  377. public:
  378. APU(int rate) : SampleRate(rate) {
  379. Reset();
  380. }
  381. void WriteReg(int Addr, byte Val);
  382. byte Read4015();
  383. void Reset ();
  384. int16 GetSample();
  385. };
  386. void APU::WriteReg(int Addr, byte Val) {
  387. switch (Addr) {
  388. case 0x000: _square0.Write(0,Val); break;
  389. case 0x001: _square0.Write(1,Val); break;
  390. case 0x002: _square0.Write(2,Val); break;
  391. case 0x003: _square0.Write(3,Val); break;
  392. case 0x004: _square1.Write(0,Val); break;
  393. case 0x005: _square1.Write(1,Val); break;
  394. case 0x006: _square1.Write(2,Val); break;
  395. case 0x007: _square1.Write(3,Val); break;
  396. case 0x008: _triangle.Write(0,Val); break;
  397. case 0x009: _triangle.Write(1,Val); break;
  398. case 0x00A: _triangle.Write(2,Val); break;
  399. case 0x00B: _triangle.Write(3,Val); break;
  400. case 0x00C: _noise.Write(0,Val); break;
  401. case 0x00D: _noise.Write(1,Val); break;
  402. case 0x00E: _noise.Write(2,Val); break;
  403. case 0x00F: _noise.Write(3,Val); break;
  404. case 0x015: _square0.Write(4,Val & 0x1);
  405. _square1.Write(4,Val & 0x2);
  406. _triangle.Write(4,Val & 0x4);
  407. _noise.Write(4,Val & 0x8);
  408. break;
  409. default:
  410. break;
  411. }
  412. }
  413. byte APU::Read4015() {
  414. byte result =
  415. (( _square0.GetTimer()) ? 0x01 : 0) |
  416. (( _square1.GetTimer()) ? 0x02 : 0) |
  417. ((_triangle.GetTimer()) ? 0x04 : 0) |
  418. (( _noise.GetTimer()) ? 0x08 : 0);
  419. return result;
  420. }
  421. void APU::Reset () {
  422. BufPos = 0;
  423. _square0.Reset();
  424. _square1.Reset();
  425. _triangle.Reset();
  426. _noise.Reset();
  427. Frame.Num = 0;
  428. Frame.Cycles = 1;
  429. }
  430. template<class T>
  431. int step(T &obj, int sampcycles, uint frame_Cycles, int frame_Num) {
  432. int samppos = 0;
  433. while (sampcycles) {
  434. // Compute the maximal amount we can step ahead before triggering
  435. // an action (i.e. compute the minimum of sampcycles, frame_Cycles
  436. // and obj.Cycles).
  437. uint max_step = sampcycles;
  438. if (max_step > frame_Cycles)
  439. max_step = frame_Cycles;
  440. if (max_step > obj.Cycles)
  441. max_step = obj.Cycles;
  442. // During all but the last of these steps, we just add the value of obj.Pos
  443. // to samppos -- so we can to that all at once with a simple multiplication:
  444. samppos += obj.Pos * (max_step - 1);
  445. // Now step ahead...
  446. sampcycles -= max_step;
  447. frame_Cycles -= max_step;
  448. obj.Cycles -= max_step;
  449. if (!frame_Cycles) {
  450. frame_Cycles = 7457;
  451. if (frame_Num < 4) {
  452. obj.QuarterFrame();
  453. if (frame_Num & 1)
  454. frame_Cycles++;
  455. else
  456. obj.HalfFrame();
  457. frame_Num++;
  458. } else
  459. frame_Num = 0;
  460. }
  461. if (!obj.Cycles)
  462. obj.Run();
  463. samppos += obj.Pos;
  464. }
  465. return samppos;
  466. }
  467. int16 APU::GetSample() {
  468. int samppos = 0;
  469. const int sampcycles = 1+(1789773-BufPos-1)/SampleRate;
  470. BufPos = BufPos + sampcycles * SampleRate - 1789773;
  471. samppos += step( _square0, sampcycles, Frame.Cycles, Frame.Num);
  472. samppos += step( _square1, sampcycles, Frame.Cycles, Frame.Num);
  473. samppos += step(_triangle, sampcycles, Frame.Cycles, Frame.Num);
  474. samppos += step( _noise, sampcycles, Frame.Cycles, Frame.Num);
  475. uint tmp = sampcycles;
  476. while (tmp >= Frame.Cycles) {
  477. tmp -= Frame.Cycles;
  478. Frame.Cycles = 7457;
  479. if (Frame.Num < 4) {
  480. if (Frame.Num & 1)
  481. Frame.Cycles++;
  482. Frame.Num++;
  483. } else
  484. Frame.Num = 0;
  485. }
  486. Frame.Cycles -= tmp;
  487. return (samppos << 6) / sampcycles;
  488. }
  489. } // End of namespace APUe
  490. Player_NES::Player_NES(ScummEngine *scumm, Audio::Mixer *mixer) {
  491. int i;
  492. _vm = scumm;
  493. _mixer = mixer;
  494. _sampleRate = _mixer->getOutputRate();
  495. _apu = new APUe::APU(_sampleRate);
  496. _samples_per_frame = _sampleRate / 60;
  497. _current_sample = 0;
  498. for (i = 0; i < NUMSLOTS; i++) {
  499. _slot[i].id = -1;
  500. _slot[i].framesleft = 0;
  501. _slot[i].type = 0;
  502. _slot[i].offset = 0;
  503. _slot[i].data = NULL;
  504. }
  505. for (i = 0; i < NUMCHANS; i++) {
  506. _mchan[i].command = 0;
  507. _mchan[i].framedelay = 0;
  508. _mchan[i].pitch = 0;
  509. _mchan[i].volume = 0;
  510. _mchan[i].voldelta = 0;
  511. _mchan[i].envflags = 0;
  512. _mchan[i].cmdlock = 0;
  513. }
  514. isSFXplaying = wasSFXplaying = false;
  515. auxData1 = auxData2 = NULL;
  516. numNotes = 0;
  517. APU_writeControl(0);
  518. _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
  519. }
  520. Player_NES::~Player_NES() {
  521. _mixer->stopHandle(_soundHandle);
  522. delete _apu;
  523. }
  524. void Player_NES::setMusicVolume (int vol) {
  525. _maxvol = vol;
  526. }
  527. int Player_NES::readBuffer(int16 *buffer, const int numSamples) {
  528. for (int n = 0; n < numSamples; n++) {
  529. buffer[n] = _apu->GetSample() * _maxvol / 255;
  530. _current_sample++;
  531. if (_current_sample == _samples_per_frame) {
  532. _current_sample = 0;
  533. sound_play();
  534. }
  535. }
  536. return numSamples;
  537. }
  538. void Player_NES::stopAllSounds() {
  539. for (int i = 0; i < NUMSLOTS; i++) {
  540. _slot[i].framesleft = 0;
  541. _slot[i].type = 0;
  542. _slot[i].id = -1;
  543. }
  544. isSFXplaying = 0;
  545. checkSilenceChannels(0);
  546. }
  547. void Player_NES::stopSound(int nr) {
  548. if (nr == -1)
  549. return;
  550. for (int i = 0; i < NUMSLOTS; i++) {
  551. if (_slot[i].id != nr)
  552. continue;
  553. isSFXplaying = 0;
  554. _slot[i].framesleft = 0;
  555. _slot[i].type = 0;
  556. _slot[i].id = -1;
  557. checkSilenceChannels(i);
  558. }
  559. }
  560. void Player_NES::startSound(int nr) {
  561. byte *data = _vm->getResourceAddress(rtSound, nr) + 2;
  562. assert(data);
  563. int soundType = data[1];
  564. int chan = data[0];
  565. if (chan == 4) {
  566. if (_slot[2].framesleft)
  567. return;
  568. chan = 0;
  569. }
  570. if (soundType < _slot[chan].type)
  571. return;
  572. _slot[chan].type = soundType;
  573. _slot[chan].id = nr;
  574. _slot[chan].data = data;
  575. _slot[chan].offset = 2;
  576. _slot[chan].framesleft = 1;
  577. checkSilenceChannels(chan);
  578. if (chan == 2) {
  579. numNotes = _slot[chan].data[2];
  580. auxData1 = _slot[chan].data + 3;
  581. auxData2 = auxData1 + numNotes;
  582. _slot[chan].data = auxData2 + numNotes;
  583. _slot[chan].offset = 0;
  584. for (int i = 0; i < NUMCHANS; i++)
  585. _mchan[i].cmdlock = 0;
  586. }
  587. }
  588. void Player_NES::checkSilenceChannels(int chan) {
  589. for (chan--; chan >= 0; chan--) {
  590. if (_slot[chan].framesleft)
  591. return;
  592. }
  593. APU_writeControl(0);
  594. }
  595. void Player_NES::sound_play() {
  596. if (_slot[0].framesleft)
  597. playSFX(0);
  598. else if (_slot[1].framesleft)
  599. playSFX(1);
  600. playMusic();
  601. }
  602. void Player_NES::playSFX (int nr) {
  603. if (--_slot[nr].framesleft)
  604. return;
  605. while (1) {
  606. int a = _slot[nr].data[_slot[nr].offset++];
  607. if (a < 16) {
  608. a >>= 2;
  609. APU_writeControl(APU_readStatus() | channelMask[a]);
  610. isSFXplaying = true;
  611. APU_writeChannel(a, 0, _slot[nr].data[_slot[nr].offset++]);
  612. APU_writeChannel(a, 1, _slot[nr].data[_slot[nr].offset++]);
  613. APU_writeChannel(a, 2, _slot[nr].data[_slot[nr].offset++]);
  614. APU_writeChannel(a, 3, _slot[nr].data[_slot[nr].offset++]);
  615. } else if (a == 0xFE) {
  616. _slot[nr].offset = 2;
  617. } else if (a == 0xFF) {
  618. _slot[nr].id = -1;
  619. _slot[nr].type = 0;
  620. isSFXplaying = false;
  621. APU_writeControl(0);
  622. if (!nr && _slot[1].framesleft) {
  623. _slot[1].framesleft = 1;
  624. isSFXplaying = true;
  625. }
  626. return;
  627. } else {
  628. _slot[nr].framesleft = _slot[nr].data[_slot[nr].offset++];
  629. return;
  630. }
  631. }
  632. }
  633. void Player_NES::playMusic() {
  634. if (!_slot[2].framesleft)
  635. return;
  636. if (wasSFXplaying && !isSFXplaying)
  637. for (int x = 1; x >= 0; x--)
  638. if (_mchan[x].cmdlock) {
  639. _mchan[x].command = _mchan[x].cmdlock;
  640. _mchan[x].framedelay = 1;
  641. }
  642. wasSFXplaying = isSFXplaying;
  643. if (!--_slot[2].framesleft) {
  644. top:
  645. int b = _slot[2].data[_slot[2].offset++];
  646. if (b == 0xFF) {
  647. _slot[2].id = -1;
  648. _slot[2].type = 0;
  649. b = 0;
  650. } else if (b == 0xFE) {
  651. _slot[2].offset = 0;
  652. goto top;
  653. } else {
  654. if (b < numNotes) {
  655. int inst = auxData1[b];
  656. int ch = instChannel[inst];
  657. _mchan[ch].pitch = auxData2[b];
  658. _mchan[ch].cmdlock = startCmd[inst];
  659. _mchan[ch].command = startCmd[inst];
  660. _mchan[ch].framedelay = 1;
  661. goto top;
  662. }
  663. b -= numNotes;
  664. if (b < 16) {
  665. int inst = b;
  666. int ch = instChannel[inst];
  667. _mchan[ch].cmdlock = 0;
  668. _mchan[ch].command = releaseCmd[inst];
  669. _mchan[ch].framedelay = 1;
  670. goto top;
  671. }
  672. b -= 16;
  673. }
  674. _slot[2].framesleft = b;
  675. }
  676. for (int x = NUMCHANS - 1; x >= 0; x--) {
  677. if (_slot[0].framesleft || _slot[1].framesleft) {
  678. _mchan[x].volume = 0;
  679. _mchan[x].framedelay = 0;
  680. continue;
  681. }
  682. if (_mchan[x].framedelay && !--_mchan[x].framedelay) {
  683. switch (_mchan[x].command) {
  684. case 0x00:
  685. case 0x13:
  686. _mchan[x].voldelta = -10;
  687. break;
  688. case 0x01:
  689. case 0x03:
  690. case 0x08:
  691. case 0x16:
  692. _mchan[x].envflags = 0x30;
  693. _mchan[x].volume = 0x6F;
  694. _mchan[x].voldelta = 0;
  695. APU_writeChannel(x, 0, 0x00);
  696. APU_writeChannel(x, 1, 0x7F);
  697. APU_writeControl(APU_readStatus() | channelMask[x]);
  698. APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
  699. APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
  700. chainCommand(x);
  701. break;
  702. case 0x02:
  703. _mchan[x].envflags = 0xB0;
  704. _mchan[x].volume = 0x6F;
  705. _mchan[x].voldelta = 0;
  706. APU_writeChannel(x, 0, 0x00);
  707. APU_writeChannel(x, 1, 0x84);
  708. APU_writeControl(APU_readStatus() | channelMask[x]);
  709. APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
  710. APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
  711. chainCommand(x);
  712. break;
  713. case 0x04:
  714. _mchan[x].envflags = 0x80;
  715. _mchan[x].volume = 0x6F;
  716. _mchan[x].voldelta = 0;
  717. APU_writeChannel(x, 0, 0x00);
  718. APU_writeChannel(x, 1, 0x7F);
  719. APU_writeControl(APU_readStatus() | channelMask[x]);
  720. APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
  721. APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
  722. chainCommand(x);
  723. break;
  724. case 0x05:
  725. _mchan[x].envflags = 0xF0;
  726. _mchan[x].volume = 0x6F;
  727. _mchan[x].voldelta = -15;
  728. APU_writeChannel(x, 1, 0x7F);
  729. APU_writeControl(APU_readStatus() | channelMask[x]);
  730. APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
  731. APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
  732. chainCommand(x);
  733. break;
  734. case 0x06:
  735. _mchan[x].pitch += 0x18;
  736. _mchan[x].envflags = 0x80;
  737. _mchan[x].volume = 0x6F;
  738. _mchan[x].voldelta = 0;
  739. APU_writeChannel(x, 0, 0x00);
  740. APU_writeChannel(x, 1, 0x7F);
  741. APU_writeControl(APU_readStatus() | channelMask[x]);
  742. APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
  743. APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
  744. chainCommand(x);
  745. break;
  746. case 0x07:
  747. APU_writeChannel(x, 2, freqTable[_mchan[x].pitch - 0x0C] & 0xFF);
  748. APU_writeChannel(x, 3, freqTable[_mchan[x].pitch - 0x0C] >> 8);
  749. chainCommand(x);
  750. break;
  751. case 0x09:
  752. _mchan[x].voldelta = -2;
  753. APU_writeChannel(x, 1, 0x7F);
  754. APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
  755. APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
  756. chainCommand(x);
  757. break;
  758. case 0x0A:
  759. APU_writeChannel(x, 1, 0x86);
  760. APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
  761. APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
  762. chainCommand(x);
  763. break;
  764. case 0x0B: case 0x1A:
  765. _mchan[x].envflags = 0x70;
  766. _mchan[x].volume = 0x6F;
  767. _mchan[x].voldelta = 0;
  768. APU_writeChannel(x, 0, 0x00);
  769. APU_writeChannel(x, 1, 0x7F);
  770. APU_writeControl(APU_readStatus() | channelMask[x]);
  771. APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
  772. APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
  773. chainCommand(x);
  774. break;
  775. case 0x0C:
  776. _mchan[x].envflags = 0xB0;
  777. chainCommand(x);
  778. break;
  779. case 0x0D:
  780. _mchan[x].envflags = 0x30;
  781. _mchan[x].volume = 0x5F;
  782. _mchan[x].voldelta = -22;
  783. APU_writeChannel(x, 0, 0x00);
  784. APU_writeControl(APU_readStatus() | channelMask[x]);
  785. APU_writeChannel(x, 2, _mchan[x].pitch & 0xF);
  786. APU_writeChannel(x, 3, 0xFF);
  787. chainCommand(x);
  788. break;
  789. case 0x0E:
  790. case 0x10:
  791. _mchan[x].envflags = 0x30;
  792. _mchan[x].volume = 0x5F;
  793. _mchan[x].voldelta = -6;
  794. APU_writeChannel(x, 0, 0x00);
  795. APU_writeControl(APU_readStatus() | channelMask[x]);
  796. APU_writeChannel(x, 2, _mchan[x].pitch & 0xF);
  797. APU_writeChannel(x, 3, 0xFF);
  798. chainCommand(x);
  799. break;
  800. case 0x0F:
  801. chainCommand(x);
  802. break;
  803. case 0x11:
  804. APU_writeChannel(x, 2, _mchan[x].pitch & 0xF);
  805. APU_writeChannel(x, 3, 0xFF);
  806. chainCommand(x);
  807. break;
  808. case 0x12:
  809. APU_writeChannel(x, 2, (_mchan[x].pitch + 3) & 0xF);
  810. APU_writeChannel(x, 3, 0xFF);
  811. chainCommand(x);
  812. break;
  813. case 0x14:
  814. _mchan[x].voldelta = -12;
  815. APU_writeChannel(x, 1, 0x8C);
  816. chainCommand(x);
  817. break;
  818. case 0x15:
  819. _mchan[x].voldelta = -12;
  820. APU_writeChannel(x, 1, 0x84);
  821. chainCommand(x);
  822. break;
  823. case 0x17:
  824. _mchan[x].pitch += 0x0C;
  825. _mchan[x].envflags = 0x80;
  826. _mchan[x].volume = 0x6F;
  827. _mchan[x].voldelta = 0;
  828. APU_writeChannel(x, 0, 0x00);
  829. APU_writeChannel(x, 1, 0x7F);
  830. APU_writeControl(APU_readStatus() | channelMask[x]);
  831. APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
  832. APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
  833. chainCommand(x);
  834. break;
  835. case 0x18:
  836. _mchan[x].envflags = 0x70;
  837. chainCommand(x);
  838. break;
  839. case 0x19:
  840. _mchan[x].envflags = 0xB0;
  841. chainCommand(x);
  842. break;
  843. case 0x1B:
  844. _mchan[x].envflags = 0x00;
  845. _mchan[x].voldelta = -10;
  846. break;
  847. default:
  848. break;
  849. }
  850. }
  851. _mchan[x].volume += _mchan[x].voldelta;
  852. _mchan[x].volume = CLIP(_mchan[x].volume, 0, MAXVOLUME);
  853. APU_writeChannel(x, 0, (_mchan[x].volume >> 3) | _mchan[x].envflags);
  854. }
  855. }
  856. void Player_NES::chainCommand(int c) {
  857. int i = _mchan[c].command;
  858. _mchan[c].command = nextCmd[i];
  859. _mchan[c].framedelay = nextDelay[i];
  860. }
  861. int Player_NES::getSoundStatus(int nr) const {
  862. for (int i = 0; i < NUMSLOTS; i++)
  863. if (_slot[i].id == nr)
  864. return 1;
  865. return 0;
  866. }
  867. void Player_NES::APU_writeChannel(int chan, int offset, byte value) {
  868. _apu->WriteReg(0x000 + 4 * chan + offset, value);
  869. }
  870. void Player_NES::APU_writeControl(byte value) {
  871. _apu->WriteReg(0x015, value);
  872. }
  873. byte Player_NES::APU_readStatus() {
  874. return _apu->Read4015();
  875. }
  876. } // End of namespace Scumm
  877. #endif // DISABLE_NES_APU