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