Skip to content

Commit cc53770

Browse files
committed
2026-05-15 16:35:43
1 parent 3b6d449 commit cc53770

3 files changed

Lines changed: 44 additions & 54 deletions

File tree

src/apu.rs

Lines changed: 42 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -660,9 +660,9 @@ struct Ns {
660660
}
661661

662662
impl Ns {
663-
fn new(sr: u32) -> Self {
663+
fn power_up() -> Self {
664664
Self {
665-
buf: Blip::power_up(sr),
665+
buf: Blip::power_up(SAMPLE_RATE),
666666
reg: Reg::power_up(),
667667
tmr: Tmr::power_up(8),
668668
lc: Lc::power_up(),
@@ -751,61 +751,53 @@ const RD: [u8; 0x30] = [
751751

752752
pub struct Apu {
753753
glo: Rc<RefCell<Global>>,
754-
pub buffer: Arc<Mutex<Vec<(f32, f32)>>>,
755-
sr: u32,
756754

757-
// NR50/51/52
758-
nr50: u8,
759-
nr51: u8,
760-
pwr: bool,
755+
pub data: Arc<Mutex<Vec<(f32, f32)>>>,
756+
pub sdiv: u16,
761757

762758
ch1: Sq1,
763759
ch2: Sq2,
764760
ch3: Wv,
765761
ch4: Ns,
766-
767-
// Frame sequencer + 512 Hz divider.
762+
fc: u32,
768763
fs: Fseq,
764+
fs_skip: bool,
769765
ft: Tmr,
770-
skip_fs: bool,
771-
772-
// sdiv at the moment of the current APU bus write; the MMU writes this
773-
// before every `sb` so the NR52 power-on handler can phase-align FS.
774-
pub sdiv_cache: u16,
775-
776-
// Monotonic frame counter (one per FS-divider fire); used together with
777-
// `t_frame`/`t_apu_n` in CH3 to extrapolate live wave-RAM access.
778-
fc: u32,
766+
nr50: u8,
767+
nr51: u8,
768+
pwr: bool,
769+
sr: u32,
779770
}
780771

781772
impl Apu {
782773
pub fn power_up(glo: Rc<RefCell<Global>>, sr: u32) -> Self {
783774
Self {
784775
glo,
785-
buffer: Arc::new(Mutex::new(Vec::new())),
786-
sr,
787-
nr50: 0,
788-
nr51: 0,
789-
pwr: false,
776+
data: Arc::new(Mutex::new(Vec::new())),
777+
sdiv: 0,
790778
ch1: Sq1::power_up(),
791779
ch2: Sq2::power_up(),
792780
ch3: Wv::power_up(),
793-
ch4: Ns::new(sr),
781+
ch4: Ns::power_up(),
782+
fc: 0,
794783
fs: Fseq::power_up(),
784+
fs_skip: false,
795785
ft: Tmr::power_up(CLOCK_FREQUENCY / 512),
796-
skip_fs: false,
797-
sdiv_cache: 0,
798-
fc: 0,
786+
nr50: 0,
787+
nr51: 0,
788+
pwr: false,
789+
sr,
799790
}
800791
}
801792

802-
// ─── Mixer & output ────────────────────────────────────────────────────
803-
804-
fn vol_l(&self) -> f32 {
805-
f32::from((self.nr50 >> 4) & 0x07) / 7.0 / 15.0 * 0.25
806-
}
807-
fn vol_r(&self) -> f32 {
808-
f32::from(self.nr50 & 0x07) / 7.0 / 15.0 * 0.25
793+
fn add(&self, l: &[f32], r: &[f32]) {
794+
let mut b = self.data.lock().unwrap();
795+
for (a, c) in l.iter().zip(r) {
796+
if b.len() > self.sr as usize {
797+
return;
798+
}
799+
b.push((*a, *c));
800+
}
809801
}
810802

811803
fn mix(&mut self) {
@@ -846,19 +838,17 @@ impl Apu {
846838
mix_into(&t[..c4], &mut l, &mut r, pan & 0x80 != 0, pan & 0x08 != 0);
847839

848840
debug_assert!(c1 == c2 && c2 == c3 && c3 == c4);
849-
self.push(&l[..c1], &r[..c1]);
841+
self.add(&l[..c1], &r[..c1]);
850842
done += c1;
851843
}
852844
}
853845

854-
fn push(&self, l: &[f32], r: &[f32]) {
855-
let mut b = self.buffer.lock().unwrap();
856-
for (a, c) in l.iter().zip(r) {
857-
if b.len() > self.sr as usize {
858-
return;
859-
}
860-
b.push((*a, *c));
861-
}
846+
fn vol_l(&self) -> f32 {
847+
f32::from((self.nr50 >> 4) & 0x07) / 7.0 / 15.0 * 0.25
848+
}
849+
850+
fn vol_r(&self) -> f32 {
851+
f32::from(self.nr50 & 0x07) / 7.0 / 15.0 * 0.25
862852
}
863853

864854
// ─── Helpers ───────────────────────────────────────────────────────────
@@ -932,8 +922,8 @@ impl Apu {
932922
// the next falling edge of sdiv bit 12. If that bit is already high at
933923
// power-on, the very first FS event is skipped (hardware glitch).
934924
self.fs.s = 7;
935-
self.ft.n = u32::from(self.sdiv_cache) % (CLOCK_FREQUENCY / 512);
936-
self.skip_fs = self.sdiv_cache & 0x1000 != 0;
925+
self.ft.n = u32::from(self.sdiv) % (CLOCK_FREQUENCY / 512);
926+
self.fs_skip = self.sdiv & 0x1000 != 0;
937927
}
938928

939929
fn status(&self) -> u8 {
@@ -1030,7 +1020,7 @@ impl Memory for Apu {
10301020
0xff1d => {
10311021
// Record d1 (2-MHz cycles from first trigger to this NR33 write).
10321022
if self.glo.borrow().term == Term::DMG && self.ch3.on && self.ch3.reg.dac_wv() {
1033-
let dt = self.sdiv_cache.wrapping_sub(self.ch3.t_s_div) as u32;
1023+
let dt = self.sdiv.wrapping_sub(self.ch3.t_s_div) as u32;
10341024
self.ch3.d1 = dt / 2;
10351025
}
10361026
self.ch3.sb(a, v);
@@ -1059,7 +1049,7 @@ impl Memory for Apu {
10591049
impl Apu {
10601050
fn nr34sb(&mut self, v: u8, xtra: bool) {
10611051
let was = self.ch3.on && self.ch3.reg.dac_wv();
1062-
let sdiv = self.sdiv_cache;
1052+
let sdiv = self.sdiv;
10631053
let trig = v & 0x80 != 0;
10641054

10651055
let dmg_off = if trig && was && self.glo.borrow().term == Term::DMG {
@@ -1113,8 +1103,8 @@ impl Ticker for Apu {
11131103

11141104
if !self.pwr {
11151105
for _ in 0..n {
1116-
if self.skip_fs {
1117-
self.skip_fs = false;
1106+
if self.fs_skip {
1107+
self.fs_skip = false;
11181108
continue;
11191109
}
11201110
self.fs.step();
@@ -1124,8 +1114,8 @@ impl Ticker for Apu {
11241114
}
11251115

11261116
for _ in 0..n {
1127-
if self.skip_fs {
1128-
self.skip_fs = false;
1117+
if self.fs_skip {
1118+
self.fs_skip = false;
11291119
self.fc = self.fc.wrapping_add(1);
11301120
continue;
11311121
}

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ fn mode_minifb(argu: &Argument) {
140140
rog::debugln!("Stream config: {:?}", config);
141141

142142
let apu = Apu::power_up(mbrd.mmu.borrow().glo.clone(), config.sample_rate.0);
143-
let apu_data = apu.buffer.clone();
143+
let apu_data = apu.data.clone();
144144
mbrd.mmu.borrow_mut().apu = apu;
145145

146146
stream = match sample_format {

src/mmu.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl Memory for Mmu {
144144
0xff04..=0xff07 => self.ticker.sb(a, v),
145145
0xff0f => self.intr.sb(0xff0f, v),
146146
0xff10..=0xff3f => {
147-
self.apu.sdiv_cache = self.glo.borrow().sdiv;
147+
self.apu.sdiv = self.glo.borrow().sdiv;
148148
self.apu.sb(a, v);
149149
}
150150
0xff40..=0xff45 => self.gpu.sb(a, v),

0 commit comments

Comments
 (0)