1 //////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // Nestopia - NES/Famicom emulator written in C++ 4 // 5 // Copyright (C) 2003-2008 Martin Freij 6 // 7 // This file is part of Nestopia. 8 // 9 // Nestopia is free software; you can redistribute it and/or modify 10 // it under the terms of the GNU General Public License as published by 11 // the Free Software Foundation; either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Nestopia is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Nestopia; if not, write to the Free Software 21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 // 23 //////////////////////////////////////////////////////////////////////////////////////// 24 25 #ifndef NST_CPU_H 26 #error Do not include NstApu.h directly! 27 #endif 28 29 #include "NstSoundRenderer.hpp" 30 31 namespace Nes 32 { 33 namespace Core 34 { 35 namespace Sound 36 { 37 class Output; 38 } 39 40 namespace State 41 { 42 class Saver; 43 class Loader; 44 } 45 46 class Cpu; 47 48 class Apu 49 { 50 public: 51 52 explicit Apu(Cpu&); 53 void Reset(bool); 54 void PowerOff(); 55 void ClearBuffers(); 56 void BeginFrame(Sound::Output*); 57 void EndFrame(); 58 void WriteFrameCtrl(uint); 59 Cycle Clock(); 60 void ClockDMA(uint=0); 61 62 Result SetSampleRate(dword); 63 Result SetSampleBits(uint); 64 Result SetSpeed(uint); 65 Result SetVolume(uint,uint); 66 uint GetVolume(uint) const; 67 uint GetCtrl(); 68 void Mute(bool); 69 void SetAutoTranspose(bool); 70 void SetGenie(bool); 71 void EnableStereo(bool); 72 73 void SaveState(State::Saver&,dword) const; 74 void LoadState(State::Loader&); 75 76 class NST_NO_VTABLE Channel 77 { 78 Apu& apu; 79 80 protected: 81 82 explicit Channel(Apu&); 83 ~Channel(); 84 85 void Update() const; 86 void Connect(bool); 87 dword GetSampleRate() const; 88 uint GetVolume(uint) const; 89 void GetOscillatorClock(Cycle&,uint&) const; 90 Cycle GetCpuClockBase() const; 91 uint GetCpuClockDivider() const; 92 Cycle GetCpuClock(uint=1) const; 93 bool IsMuted() const; 94 bool IsGenie() const; 95 96 public: 97 98 typedef Sound::Sample Sample; 99 100 enum 101 { 102 APU_SQUARE1, 103 APU_SQUARE2, 104 APU_TRIANGLE, 105 APU_NOISE, 106 APU_DPCM, 107 EXT_FDS, 108 EXT_MMC5, 109 EXT_VRC6, 110 EXT_VRC7, 111 EXT_N163, 112 EXT_S5B 113 }; 114 115 enum 116 { 117 OUTPUT_MIN = -32767, 118 OUTPUT_MAX = +32767, 119 OUTPUT_MUL = 256, 120 OUTPUT_DECAY = OUTPUT_MUL / 4 - 1, 121 DEFAULT_VOLUME = 85 122 }; 123 124 virtual void Reset() = 0; 125 virtual Sample GetSample() = 0; 126 virtual Cycle Clock(Cycle,Cycle,Cycle); 127 virtual bool UpdateSettings() = 0; 128 129 class LengthCounter 130 { 131 public: 132 133 LengthCounter(); 134 135 void Reset(); 136 void LoadState(State::Loader&); 137 void SaveState(State::Saver&,dword) const; 138 139 private: 140 141 uint enabled; 142 uint count; 143 144 static const byte lut[32]; 145 146 public: 147 Disable(bool disable)148 uint Disable(bool disable) 149 { 150 enabled = disable - 1U; 151 count &= enabled; 152 return enabled; 153 } 154 Write(uint data)155 void Write(uint data) 156 { 157 NST_ASSERT( (data >> 3) < sizeof(array(lut)) ); 158 count = lut[data >> 3] & enabled; 159 } 160 Write(uint data,bool frameCounterDelta)161 void Write(uint data,bool frameCounterDelta) 162 { 163 NST_VERIFY_MSG( frameCounterDelta, "APU $40xx/framecounter conflict" ); 164 165 if (frameCounterDelta || !count) 166 Write( data ); 167 } 168 GetCount() const169 uint GetCount() const 170 { 171 return count; 172 } 173 Clock()174 bool Clock() 175 { 176 return count && !--count; 177 } 178 }; 179 180 class Envelope 181 { 182 public: 183 184 Envelope(); 185 186 void Reset(); 187 void SetOutputVolume(uint); 188 void LoadState(State::Loader&); 189 void SaveState(State::Saver&,dword) const; 190 191 void Clock(); 192 void Write(uint); 193 194 private: 195 196 void UpdateOutput(); 197 198 dword output; 199 uint outputVolume; 200 byte regs[2]; 201 byte count; 202 bool reset; 203 204 public: 205 Looping() const206 bool Looping() const 207 { 208 return regs[1] & 0x20U; 209 } 210 Volume() const211 dword Volume() const 212 { 213 return output; 214 } 215 ResetClock()216 void ResetClock() 217 { 218 reset = true; 219 } 220 }; 221 222 class DcBlocker 223 { 224 public: 225 226 DcBlocker(); 227 228 void Reset(); 229 Sample Apply(Sample); 230 void LoadState(State::Loader&); 231 void SaveState(State::Saver&,dword) const; 232 233 private: 234 235 enum 236 { 237 POLE = 3 // ~0.9999 238 }; 239 240 idword prev; 241 idword next; 242 idword acc; 243 }; 244 }; 245 246 private: 247 248 typedef void (NST_FASTCALL Apu::*Updater)(Cycle); 249 250 inline void Update(Cycle); 251 void Update(); 252 void UpdateLatency(); 253 bool UpdateDelta(); 254 255 void Reset(bool,bool); 256 void CalculateOscillatorClock(Cycle&,uint&) const; 257 void Resync(dword); 258 NST_NO_INLINE void ClearBuffers(bool); 259 260 enum 261 { 262 MAX_CHANNELS = 11, 263 STATUS_NO_FRAME_IRQ = 0x40, 264 STATUS_SEQUENCE_5_STEP = 0x80, 265 STATUS_FRAME_IRQ_ENABLE = 0, 266 STATUS_BITS = STATUS_NO_FRAME_IRQ|STATUS_SEQUENCE_5_STEP, 267 NLN_VOL = 192, 268 NLN_SQ_F = 900, 269 NLN_SQ_0 = 9552UL * Channel::OUTPUT_MUL * NLN_VOL * (NLN_SQ_F/100), 270 NLN_SQ_1 = 8128UL * Channel::OUTPUT_MUL * NLN_SQ_F, 271 NLN_SQ_2 = NLN_SQ_F * 100UL, 272 NLN_TND_F = 500, 273 NLN_TND_0 = 16367UL * Channel::OUTPUT_MUL * NLN_VOL * (NLN_TND_F/100), 274 NLN_TND_1 = 24329UL * Channel::OUTPUT_MUL * NLN_TND_F, 275 NLN_TND_2 = NLN_TND_F * 100UL 276 }; 277 278 NES_DECL_POKE( 4000 ); 279 NES_DECL_POKE( 4001 ); 280 NES_DECL_POKE( 4002 ); 281 NES_DECL_POKE( 4003 ); 282 NES_DECL_POKE( 4004 ); 283 NES_DECL_POKE( 4005 ); 284 NES_DECL_POKE( 4006 ); 285 NES_DECL_POKE( 4007 ); 286 NES_DECL_POKE( 4008 ); 287 NES_DECL_POKE( 400A ); 288 NES_DECL_POKE( 400B ); 289 NES_DECL_POKE( 400C ); 290 NES_DECL_POKE( 400E ); 291 NES_DECL_POKE( 400F ); 292 NES_DECL_POKE( 4010 ); 293 NES_DECL_POKE( 4011 ); 294 NES_DECL_POKE( 4012 ); 295 NES_DECL_POKE( 4013 ); 296 NES_DECL_POKE( 4015 ); 297 NES_DECL_PEEK( 4015 ); 298 NES_DECL_PEEK( 40xx ); 299 300 NST_NO_INLINE Channel::Sample GetSample(); 301 302 void NST_FASTCALL SyncOn (Cycle); 303 void NST_FASTCALL SyncOnExt (Cycle); 304 void NST_FASTCALL SyncOff (Cycle); 305 306 NST_NO_INLINE void ClockFrameIRQ(Cycle); 307 NST_NO_INLINE void ClockFrameCounter(); 308 NST_NO_INLINE void ClockDmc(Cycle,uint=0); 309 NST_NO_INLINE void ClockOscillators(bool); 310 311 template<typename T,bool STEREO> 312 void FlushSound(); 313 314 void UpdateSettings(); 315 void UpdateVolumes(); 316 317 struct Cycles 318 { 319 Cycles(); 320 321 void Update(dword,uint,const Cpu&); 322 void Reset(bool,CpuModel); 323 324 uint fixed; 325 Cycle rate; 326 Cycle rateCounter; 327 Cycle frameCounter; 328 Cycle extCounter; 329 word frameDivider; 330 word frameIrqRepeat; 331 Cycle frameIrqClock; 332 Cycle dmcClock; 333 334 static const dword frameClocks[3][4]; 335 static const dword oscillatorClocks[3][2][4]; 336 }; 337 338 class Synchronizer 339 { 340 uint sync; 341 uint duty; 342 dword streamed; 343 dword rate; 344 345 public: 346 347 Synchronizer(); 348 349 void Reset(uint,dword,const Cpu&); 350 void Resync(uint,const Cpu&); 351 NST_SINGLE_CALL dword Clock(dword,dword,const Cpu&); 352 }; 353 354 class Oscillator 355 { 356 enum 357 { 358 RESET_CYCLES = 2048 359 }; 360 361 protected: 362 363 Oscillator(); 364 365 void Reset(); 366 void UpdateSettings(dword,uint); 367 368 ibool active; 369 idword timer; 370 Cycle rate; 371 Cycle frequency; 372 dword amp; 373 uint fixed; 374 375 public: 376 377 inline void ClearAmp(); 378 }; 379 380 class Square : public Oscillator 381 { 382 public: 383 384 void Reset(); 385 void UpdateSettings(uint,dword,uint); 386 void LoadState(State::Loader&); 387 void SaveState(State::Saver&,dword) const; 388 389 NST_SINGLE_CALL void WriteReg0(uint); 390 NST_SINGLE_CALL void WriteReg1(uint); 391 NST_SINGLE_CALL void WriteReg2(uint); 392 NST_SINGLE_CALL void WriteReg3(uint,Cycle); 393 NST_SINGLE_CALL void Disable(bool); 394 395 dword GetSample(); 396 397 NST_SINGLE_CALL void ClockEnvelope(); 398 NST_SINGLE_CALL void ClockSweep(uint); 399 400 inline uint GetLengthCounter() const; 401 402 private: 403 404 inline bool CanOutput() const; 405 void UpdateFrequency(); 406 407 enum 408 { 409 MIN_FRQ = 0x008, 410 MAX_FRQ = 0x7FF, 411 REG0_DUTY_SHIFT = 6, 412 REG1_SWEEP_SHIFT = 0x07, 413 REG1_SWEEP_DECREASE = 0x08, 414 REG1_SWEEP_RATE = 0x70, 415 REG1_SWEEP_RATE_SHIFT = 4, 416 REG1_SWEEP_ENABLED = 0x80, 417 REG3_WAVELENGTH_LOW = 0x00FF, 418 REG3_WAVELENGTH_HIGH = 0x0700 419 }; 420 421 uint step; 422 uint duty; 423 Channel::Envelope envelope; 424 Channel::LengthCounter lengthCounter; 425 bool validFrequency; 426 bool sweepReload; 427 byte sweepCount; 428 byte sweepRate; 429 uint sweepIncrease; 430 word sweepShift; 431 word waveLength; 432 }; 433 434 class Triangle : public Oscillator 435 { 436 public: 437 438 Triangle(); 439 440 void Reset(); 441 void UpdateSettings(uint,dword,uint); 442 void LoadState(State::Loader&); 443 void SaveState(State::Saver&,dword) const; 444 445 NST_SINGLE_CALL void WriteReg0(uint); 446 NST_SINGLE_CALL void WriteReg2(uint); 447 NST_SINGLE_CALL void WriteReg3(uint,Cycle); 448 NST_SINGLE_CALL void Disable(bool); 449 450 NST_SINGLE_CALL dword GetSample(); 451 452 NST_SINGLE_CALL void ClockLinearCounter(); 453 NST_SINGLE_CALL void ClockLengthCounter(); 454 455 inline uint GetLengthCounter() const; 456 457 private: 458 459 inline bool CanOutput() const; 460 461 enum 462 { 463 MIN_FRQ = 2 + 1, 464 STEP_CHECK = 0x1F, 465 REG0_LINEAR_COUNTER_LOAD = 0x7F, 466 REG0_LINEAR_COUNTER_START = 0x80, 467 REG2_WAVE_LENGTH_LOW = 0x00FF, 468 REG3_WAVE_LENGTH_HIGH = 0x0700 469 }; 470 471 enum Status 472 { 473 STATUS_COUNTING, 474 STATUS_RELOAD 475 }; 476 477 uint step; 478 uint outputVolume; 479 Status status; 480 word waveLength; 481 byte linearCtrl; 482 byte linearCounter; 483 Channel::LengthCounter lengthCounter; 484 }; 485 486 class Noise : public Oscillator 487 { 488 public: 489 490 void Reset(CpuModel); 491 void UpdateSettings(uint,dword,uint); 492 void LoadState(State::Loader&,CpuModel); 493 void SaveState(State::Saver&,dword) const; 494 495 NST_SINGLE_CALL void WriteReg0(uint); 496 NST_SINGLE_CALL void WriteReg2(uint,CpuModel); 497 NST_SINGLE_CALL void WriteReg3(uint,Cycle); 498 NST_SINGLE_CALL void Disable(bool); 499 500 NST_SINGLE_CALL dword GetSample(); 501 502 NST_SINGLE_CALL void ClockEnvelope(); 503 NST_SINGLE_CALL void ClockLengthCounter(); 504 505 inline uint GetLengthCounter() const; 506 507 private: 508 509 inline bool CanOutput() const; 510 uint GetFrequencyIndex() const; 511 512 enum 513 { 514 REG2_FREQUENCY = 0x0F, 515 REG2_93BIT_MODE = 0x80 516 }; 517 518 uint bits; 519 uint shifter; 520 Channel::Envelope envelope; 521 Channel::LengthCounter lengthCounter; 522 523 static const word lut[3][16]; 524 }; 525 526 class Dmc 527 { 528 public: 529 530 Dmc(); 531 532 void Reset(CpuModel); 533 void UpdateSettings(uint); 534 void LoadState(State::Loader&,const Cpu&,CpuModel,Cycle&); 535 void SaveState(State::Saver&,dword,const Cpu&,Cycle) const; 536 537 NST_SINGLE_CALL bool WriteReg0(uint,CpuModel); 538 NST_SINGLE_CALL void WriteReg1(uint); 539 NST_SINGLE_CALL void WriteReg2(uint); 540 NST_SINGLE_CALL void WriteReg3(uint); 541 NST_SINGLE_CALL void Disable(bool,Cpu&); 542 543 NST_SINGLE_CALL dword GetSample(); 544 545 NST_SINGLE_CALL bool ClockDAC(); 546 NST_SINGLE_CALL void Update(); 547 NST_SINGLE_CALL void ClockDMA(Cpu&,Cycle&,uint=0); 548 549 inline void ClearAmp(); 550 inline uint GetLengthCounter() const; 551 552 static Cycle GetResetFrequency(CpuModel); 553 554 private: 555 556 void DoDMA(Cpu&,Cycle,uint=0); 557 558 enum 559 { 560 REG0_FREQUENCY = 0x0F, 561 REG0_LOOP = 0x40, 562 REG0_IRQ_ENABLE = 0x80, 563 INP_STEP = 8 564 }; 565 566 uint curSample; 567 uint linSample; 568 uint outputVolume; 569 Cycle frequency; 570 571 struct 572 { 573 uint ctrl; 574 word lengthCounter; 575 word address; 576 } regs; 577 578 struct 579 { 580 byte shifter; 581 byte dac; 582 byte buffer; 583 bool active; 584 } out; 585 586 struct 587 { 588 word lengthCounter; 589 word address; 590 word buffered; 591 word buffer; 592 } dma; 593 594 static const word lut[3][16]; 595 }; 596 597 struct Settings 598 { 599 Settings(); 600 601 dword rate; 602 uint bits; 603 byte speed; 604 bool muted; 605 bool transpose; 606 bool genie; 607 bool stereo; 608 bool audible; 609 byte volumes[MAX_CHANNELS]; 610 }; 611 612 uint ctrl; 613 Updater updater; 614 Cpu& cpu; 615 Cycles cycles; 616 Synchronizer synchronizer; 617 Square square[2]; 618 Triangle triangle; 619 Noise noise; 620 Dmc dmc; 621 Channel* extChannel; 622 Channel::DcBlocker dcBlocker; 623 Sound::Output* stream; 624 Sound::Buffer buffer; 625 Settings settings; 626 627 public: 628 GetSampleRate() const629 dword GetSampleRate() const 630 { 631 return settings.rate; 632 } 633 GetSampleBits() const634 uint GetSampleBits() const 635 { 636 return settings.bits; 637 } 638 GetSpeed() const639 uint GetSpeed() const 640 { 641 return settings.speed; 642 } 643 IsAutoTransposing() const644 bool IsAutoTransposing() const 645 { 646 return settings.transpose; 647 } 648 IsGenie() const649 bool IsGenie() const 650 { 651 return settings.genie; 652 } 653 InStereo() const654 bool InStereo() const 655 { 656 return settings.stereo; 657 } 658 IsMuted() const659 bool IsMuted() const 660 { 661 return settings.muted; 662 } 663 IsAudible() const664 bool IsAudible() const 665 { 666 return settings.audible && !settings.muted; 667 } 668 }; 669 } 670 } 671