Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/gameboy/apu/square1/square1.cpp
2 views
1
#ifdef APU_CPP
2
3
bool APU::Square1::dac_enable() {
4
return (envelope_volume || envelope_direction);
5
}
6
7
void APU::Square1::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::Square1::sweep(bool update) {
26
if(sweep_enable == false) return;
27
28
sweep_negate = sweep_direction;
29
unsigned delta = frequency_shadow >> sweep_shift;
30
signed freq = frequency_shadow + (sweep_negate ? -delta : delta);
31
32
if(freq > 2047) {
33
enable = false;
34
} else if(sweep_shift && update) {
35
frequency_shadow = freq;
36
frequency = freq & 2047;
37
period = 4 * (2048 - frequency);
38
}
39
}
40
41
void APU::Square1::clock_length() {
42
if(counter && length) {
43
if(--length == 0) enable = false;
44
}
45
}
46
47
void APU::Square1::clock_sweep() {
48
if(enable && sweep_frequency && --sweep_period == 0) {
49
sweep_period = sweep_frequency;
50
sweep(1);
51
sweep(0);
52
}
53
}
54
55
void APU::Square1::clock_envelope() {
56
if(enable && envelope_frequency && --envelope_period == 0) {
57
envelope_period = envelope_frequency;
58
if(envelope_direction == 0 && volume > 0) volume--;
59
if(envelope_direction == 1 && volume < 15) volume++;
60
}
61
}
62
63
void APU::Square1::write(unsigned r, uint8 data) {
64
if(r == 0) { //$ff10 NR10
65
if(sweep_negate && sweep_direction && !(data & 0x08)) enable = false;
66
sweep_frequency = (data >> 4) & 7;
67
sweep_direction = data & 0x08;
68
sweep_shift = data & 0x07;
69
}
70
71
if(r == 1) { //$ff11 NR11
72
duty = data >> 6;
73
length = 64 - (data & 0x3f);
74
}
75
76
if(r == 2) { //$ff12 NR12
77
envelope_volume = data >> 4;
78
envelope_direction = data & 0x08;
79
envelope_frequency = data & 0x07;
80
if(dac_enable() == false) enable = false;
81
}
82
83
if(r == 3) { //$ff13 NR13
84
frequency = (frequency & 0x0700) | data;
85
}
86
87
if(r == 4) { //$ff14 NR14
88
bool initialize = data & 0x80;
89
counter = data & 0x40;
90
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
91
92
if(initialize) {
93
enable = dac_enable();
94
envelope_period = envelope_frequency;
95
volume = envelope_volume;
96
frequency_shadow = frequency;
97
sweep_period = sweep_frequency;
98
sweep_enable = sweep_period || sweep_shift;
99
sweep_negate = false;
100
if(sweep_shift) sweep(0);
101
if(length == 0) length = 64;
102
}
103
}
104
105
period = 4 * (2048 - frequency);
106
}
107
108
void APU::Square1::power() {
109
enable = 0;
110
111
sweep_frequency = 0;
112
sweep_direction = 0;
113
sweep_shift = 0;
114
sweep_negate = 0;
115
duty = 0;
116
length = 0;
117
envelope_volume = 0;
118
envelope_direction = 0;
119
envelope_frequency = 0;
120
frequency = 0;
121
counter = 0;
122
123
output = 0;
124
duty_output = 0;
125
phase = 0;
126
period = 0;
127
envelope_period = 0;
128
sweep_period = 0;
129
frequency_shadow = 0;
130
sweep_enable = 0;
131
volume = 0;
132
}
133
134
void APU::Square1::serialize(serializer &s) {
135
s.integer(enable);
136
137
s.integer(sweep_frequency);
138
s.integer(sweep_direction);
139
s.integer(sweep_shift);
140
s.integer(sweep_negate);
141
s.integer(duty);
142
s.integer(length);
143
s.integer(envelope_volume);
144
s.integer(envelope_direction);
145
s.integer(envelope_frequency);
146
s.integer(frequency);
147
s.integer(counter);
148
149
s.integer(output);
150
s.integer(duty_output);
151
s.integer(phase);
152
s.integer(period);
153
s.integer(envelope_period);
154
s.integer(sweep_period);
155
s.integer(frequency_shadow);
156
s.integer(sweep_enable);
157
s.integer(volume);
158
}
159
160
#endif
161
162