1 //
2 //   Copyright (C) 2007 by sinamas <sinamas at users.sourceforge.net>
3 //
4 //   This program is free software; you can redistribute it and/or modify
5 //   it under the terms of the GNU General Public License version 2 as
6 //   published by the Free Software Foundation.
7 //
8 //   This program is distributed in the hope that it will be useful,
9 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //   GNU General Public License version 2 for more details.
12 //
13 //   You should have received a copy of the GNU General Public License
14 //   version 2 along with this program; if not, write to the
15 //   Free Software Foundation, Inc.,
16 //   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 //
18 
19 #ifndef SOUND_CHANNEL3_H
20 #define SOUND_CHANNEL3_H
21 
22 #include "gbint.h"
23 #include "length_counter.h"
24 #include "master_disabler.h"
25 
26 namespace gambatte {
27 
28 struct SaveState;
29 
30 class Channel3 {
31 public:
32 	Channel3();
isActive()33 	bool isActive() const { return master_; }
34 	void reset();
35 	void init(bool cgb);
36 	void setStatePtrs(SaveState &state);
37 	void saveState(SaveState &state) const;
38 	void loadState(const SaveState &state);
39 	void setNr0(unsigned data);
setNr1(unsigned data)40 	void setNr1(unsigned data) { lengthCounter_.nr1Change(data, nr4_, cycleCounter_); }
41 	void setNr2(unsigned data);
setNr3(unsigned data)42 	void setNr3(unsigned data) { nr3_ = data; }
43 	void setNr4(unsigned data);
44 	void setSo(unsigned long soMask);
45 	void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles);
46 
waveRamRead(unsigned index)47 	unsigned waveRamRead(unsigned index) const {
48 		if (master_) {
49 			if (!cgb_ && cycleCounter_ != lastReadTime_)
50 				return 0xFF;
51 
52 			index = wavePos_ >> 1;
53 		}
54 
55 		return waveRam_[index];
56 	}
57 
waveRamWrite(unsigned index,unsigned data)58 	void waveRamWrite(unsigned index, unsigned data) {
59 		if (master_) {
60 			if (!cgb_ && cycleCounter_ != lastReadTime_)
61 				return;
62 
63 			index = wavePos_ >> 1;
64 		}
65 
66 		waveRam_[index] = data;
67 	}
68 
69 private:
70 	class Ch3MasterDisabler : public MasterDisabler {
71 	public:
Ch3MasterDisabler(bool & m,unsigned long & wC)72 		Ch3MasterDisabler(bool &m, unsigned long &wC) : MasterDisabler(m), waveCounter_(wC) {}
73 
operator()74 		virtual void operator()() {
75 			MasterDisabler::operator()();
76 			waveCounter_ = SoundUnit::counter_disabled;
77 		}
78 
79 	private:
80 		unsigned long &waveCounter_;
81 	};
82 
83 	unsigned char waveRam_[0x10];
84 	Ch3MasterDisabler disableMaster_;
85 	LengthCounter lengthCounter_;
86 	unsigned long cycleCounter_;
87 	unsigned long soMask_;
88 	unsigned long prevOut_;
89 	unsigned long waveCounter_;
90 	unsigned long lastReadTime_;
91 	unsigned char nr0_;
92 	unsigned char nr3_;
93 	unsigned char nr4_;
94 	unsigned char wavePos_;
95 	unsigned char rshift_;
96 	unsigned char sampleBuf_;
97 	bool master_;
98 	bool cgb_;
99 
100 	void updateWaveCounter(unsigned long cc);
101 };
102 
103 }
104 
105 #endif
106