Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/gameboy/apu/square2/square2.cpp
2 views
1
#ifdef APU_CPP
2
3
bool APU::Square2::dac_enable() {
4
return (envelope_volume || envelope_direction);
5
}
6
7
void APU::Square2::run() {
8
if(period && --period == 0) {
9
period = 4 * (2048 - frequency);
10
phase++;
11
switch(duty) {
12
case 0: duty_output = (phase == 6); break; //______-_
13
case 1: duty_output = (phase >= 6); break; //______--
14
case 2: duty_output = (phase >= 4); break; //____----
15
case 3: duty_output = (phase <= 5); break; //------__
16
}
17
}
18
19
uint4 sample = (duty_output ? volume : (uint4)0);
20
if(enable == false) sample = 0;
21
22
output = sample;
23
}
24
25
void APU::Square2::clock_length() {
26
if(counter && length) {
27
if(--length == 0) enable = false;
28
}
29
}
30
31
void APU::Square2::clock_envelope() {
32
if(enable && envelope_frequency && --envelope_period == 0) {
33
envelope_period = envelope_frequency;
34
if(envelope_direction == 0 && volume > 0) volume--;
35
if(envelope_direction == 1 && volume < 15) volume++;
36
}
37
}
38
39
void APU::Square2::write(unsigned r, uint8 data) {
40
if(r == 1) { //$ff16 NR21
41
duty = data >> 6;
42
length = 64 - (data & 0x3f);
43
}
44
45
if(r == 2) { //$ff17 NR22
46
envelope_volume = data >> 4;
47
envelope_direction = data & 0x08;
48
envelope_frequency = data & 0x07;
49
if(dac_enable() == false) enable = false;
50
}
51
52
if(r == 3) { //$ff18 NR23
53
frequency = (frequency & 0x0700) | data;
54
}
55
56
if(r == 4) { //$ff19 NR24
57
bool initialize = data & 0x80;
58
counter = data & 0x40;
59
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
60
61
if(initialize) {
62
enable = dac_enable();
63
envelope_period = envelope_frequency;
64
volume = envelope_volume;
65
if(length == 0) length = 64;
66
}
67
}
68
69
period = 4 * (2048 - frequency);
70
}
71
72
void APU::Square2::power() {
73
enable = 0;
74
75
duty = 0;
76
length = 0;
77
envelope_volume = 0;
78
envelope_direction = 0;
79
envelope_frequency = 0;
80
frequency = 0;
81
counter = 0;
82
83
output = 0;
84
duty_output = 0;
85
phase = 0;
86
period = 0;
87
envelope_period = 0;
88
volume = 0;
89
}
90
91
void APU::Square2::serialize(serializer &s) {
92
s.integer(enable);
93
94
s.integer(duty);
95
s.integer(length);
96
s.integer(envelope_volume);
97
s.integer(envelope_direction);
98
s.integer(envelope_frequency);
99
s.integer(frequency);
100
s.integer(counter);
101
102
s.integer(output);
103
s.integer(duty_output);
104
s.integer(phase);
105
s.integer(period);
106
s.integer(envelope_period);
107
s.integer(volume);
108
}
109
110
#endif
111
112