@@ -851,18 +851,8 @@ impl Apu {
851851 f32:: from ( self . nr50 & 0x07 ) / 7.0 / 15.0 * 0.25
852852 }
853853
854- // ─── Helpers ───────────────────────────────────────────────────────────
855-
856- fn xtra_clock ( & self ) -> bool {
857- // "First half" of the length period (Pan Docs obscure behaviour): the
858- // FS step just past an even step. step%2==0 means the *next* clock will
859- // be a length clock, i.e. we are in the half that triggers extras.
860- self . fs . s & 1 == 0
861- }
862-
863- /// Compute the live wave sample index based on elapsed T-cycles since the
864- /// last trigger. The wave timer fires once every period T-cycles after an
865- /// initial `period_at_trigger + 6` T-cycle warm-up.
854+ // Compute the live wave sample index based on elapsed T-cycles since the last trigger. The wave timer fires once
855+ // every period T-cycles after an initial period_at_trigger + 6 T-cycle warm-up.
866856 fn live_wave ( & self ) -> u64 {
867857 let p_now = u64:: from ( self . ch3 . tmr . p ) ;
868858 let p_trg = u64:: from ( self . ch3 . p1 ) ;
@@ -888,9 +878,8 @@ impl Apu {
888878 elapsed - t_last < 2
889879 }
890880
891- fn power_off ( & mut self ) {
892- // Zero every channel register except wave RAM and (on DMG) length
893- // counters.
881+ fn power_no ( & mut self ) {
882+ // Zero every channel register except wave RAM and (on DMG) length counters.
894883 for i in 0 ..5 {
895884 self . ch1 . reg . n [ i] = 0 ;
896885 }
@@ -918,9 +907,8 @@ impl Apu {
918907 }
919908
920909 fn power_on ( & mut self ) {
921- // Phase-align the frame sequencer with DIV: the next FS clock occurs at
922- // the next falling edge of sdiv bit 12. If that bit is already high at
923- // power-on, the very first FS event is skipped (hardware glitch).
910+ // Phase-align the frame sequencer with DIV: the next FS clock occurs at the next falling edge of sdiv bit 12.
911+ // If that bit is already high at power-on, the very first FS event is skipped (hardware glitch).
924912 self . fs . s = 7 ;
925913 self . ft . n = u32:: from ( self . sdiv ) % ( CLOCK_FREQUENCY / 512 ) ;
926914 self . fs_skip = self . sdiv & 0x1000 != 0 ;
@@ -935,10 +923,6 @@ impl Apu {
935923 }
936924}
937925
938- // ────────────────────────────────────────────────────────────────────────────
939- // Memory bus.
940- // ────────────────────────────────────────────────────────────────────────────
941-
942926impl Memory for Apu {
943927 fn lb ( & self , a : u16 ) -> u8 {
944928 let v = match a {
@@ -974,9 +958,8 @@ impl Memory for Apu {
974958 }
975959
976960 fn sb ( & mut self , a : u16 , v : u8 ) {
977- // Power gating: all channel/NR50/NR51 writes are blocked while the APU
978- // is off, except wave RAM and NR52 itself. On DMG, length-counter
979- // pre-loads via NRx1 remain writable.
961+ // Power gating: all channel/NR50/NR51 writes are blocked while the APU is off, except wave RAM and NR52
962+ // itself. On DMG, length-counter pre-loads via NRx1 remain writable.
980963 if !self . pwr && a != 0xff26 && !( 0xff30 ..=0xff3f ) . contains ( & a) {
981964 if self . glo . borrow ( ) . term == Term :: DMG {
982965 match a {
@@ -1002,7 +985,9 @@ impl Memory for Apu {
1002985 return ;
1003986 }
1004987
1005- let xtra = self . xtra_clock ( ) ;
988+ // First half of the length period (Pan Docs obscure behaviour): the FS step just past an even step. step%2==0
989+ // means the next clock will be a length clock, i.e. we are in the half that triggers extras.
990+ let xtra = self . fs . s & 1 == 0 ;
1006991 match a {
1007992 0xff10 => {
1008993 if self . ch1 . fs . nr10di ( & self . ch1 . reg , v) {
@@ -1034,13 +1019,28 @@ impl Memory for Apu {
10341019 let was = self . pwr ;
10351020 self . pwr = v & 0x80 != 0 ;
10361021 if was && !self . pwr {
1037- self . power_off ( ) ;
1022+ self . power_no ( ) ;
10381023 } else if !was && self . pwr {
10391024 self . power_on ( ) ;
10401025 }
10411026 }
10421027 0xff27 ..=0xff2f => { }
1043- 0xff30 ..=0xff3f => self . write_wave_ram ( a, v) ,
1028+ 0xff30 ..=0xff3f => {
1029+ if self . ch3 . on && self . ch3 . reg . dac_wv ( ) {
1030+ let fires = self . live_wave ( ) ;
1031+ let addr = self . wave_addr ( fires) ;
1032+ match self . glo . borrow ( ) . term {
1033+ Term :: CGB => self . ch3 . ram [ addr] = v,
1034+ Term :: DMG => {
1035+ if self . dmg_wave_window ( fires) {
1036+ self . ch3 . ram [ addr] = v;
1037+ }
1038+ }
1039+ }
1040+ } else {
1041+ self . ch3 . ram [ ( a - 0xff30 ) as usize ] = v;
1042+ }
1043+ }
10441044 _ => unreachable ! ( ) ,
10451045 }
10461046 }
@@ -1061,46 +1061,22 @@ impl Apu {
10611061 } ;
10621062
10631063 if trig {
1064- // Record live-wave snapshot before sb_nrx4 reloads the timer.
10651064 self . ch3 . t_s_div = sdiv;
10661065 self . ch3 . d1 = 0 ;
10671066 self . ch3 . t_apu_n = self . ft . n ;
10681067 self . ch3 . t_frame = self . fc ;
10691068 }
10701069 self . ch3 . nrx4sb ( v, xtra, dmg_off) ;
10711070 if trig {
1072- // p1 takes the *new* period (post-NR34 high-bits).
10731071 self . ch3 . p1 = self . ch3 . tmr . p ;
10741072 }
10751073 }
1076-
1077- fn write_wave_ram ( & mut self , a : u16 , v : u8 ) {
1078- if self . ch3 . on && self . ch3 . reg . dac_wv ( ) {
1079- let fires = self . live_wave ( ) ;
1080- let addr = self . wave_addr ( fires) ;
1081- match self . glo . borrow ( ) . term {
1082- Term :: CGB => self . ch3 . ram [ addr] = v,
1083- Term :: DMG => {
1084- if self . dmg_wave_window ( fires) {
1085- self . ch3 . ram [ addr] = v;
1086- }
1087- }
1088- }
1089- } else {
1090- self . ch3 . ram [ ( a - 0xff30 ) as usize ] = v;
1091- }
1092- }
10931074}
10941075
1095- // ────────────────────────────────────────────────────────────────────────────
1096- // Clocking.
1097- // ────────────────────────────────────────────────────────────────────────────
1098-
10991076impl Ticker for Apu {
11001077 fn tick ( & mut self , cycles : u16 ) {
11011078 // The DIV-APU 512 Hz counter runs regardless of power state.
11021079 let n = self . ft . step ( u32:: from ( cycles) ) ;
1103-
11041080 if !self . pwr {
11051081 for _ in 0 ..n {
11061082 if self . fs_skip {
@@ -1112,20 +1088,17 @@ impl Ticker for Apu {
11121088 }
11131089 return ;
11141090 }
1115-
11161091 for _ in 0 ..n {
11171092 if self . fs_skip {
11181093 self . fs_skip = false ;
11191094 self . fc = self . fc . wrapping_add ( 1 ) ;
11201095 continue ;
11211096 }
1122-
11231097 let p = self . ft . p ;
11241098 self . ch1 . step ( p) ;
11251099 self . ch2 . step ( p) ;
11261100 self . ch3 . step ( p) ;
11271101 self . ch4 . step ( p) ;
1128-
11291102 let s = self . fs . step ( ) ;
11301103 if Fseq :: len ( s) {
11311104 if self . ch1 . lc . step ( & self . ch1 . reg ) {
@@ -1158,7 +1131,6 @@ impl Ticker for Apu {
11581131 }
11591132 self . ch1 . tmr . p = self . ch1 . reg . per_sq ( ) ;
11601133 }
1161-
11621134 self . ch1 . buf . end ( p) ;
11631135 self . ch2 . buf . end ( p) ;
11641136 self . ch3 . buf . end ( p) ;
@@ -1169,30 +1141,25 @@ impl Ticker for Apu {
11691141 }
11701142}
11711143
1172- // ────────────────────────────────────────────────────────────────────────────
11731144// DMG wave-RAM corruption timing model (SameBoy-compatible).
11741145//
1175- // The internal sample-countdown is loaded with `p1/2 + 2` 2-MHz cycles after
1176- // the first trigger and reset to `p/2 − 1` on every fire (where p is the
1177- // current period in T-cycles). Re-triggering while `sample_countdown == 0`
1178- // corrupts wave RAM at byte offset `((csi + 1) >> 1) & 0xF`.
1146+ // The internal sample-countdown is loaded with p1/2 + 2 2-MHz cycles after the first trigger and reset to p/2 − 1
1147+ // on every fire (where p is the current period in T-cycles). Re-triggering while sample_countdown == 0. Corrupts wave
1148+ // RAM at byte offset ((csi + 1) >> 1) & 0xF.
11791149//
1180- // p1_h P1/2 (2-MHz cycles) at first trigger
1181- // d1 2-MHz cycles between the first trigger and the last NR33 write
1182- // d2 2-MHz cycles between that NR33 write and the re-trigger
1183- // p2_h P2/2 (2-MHz cycles) — the current period
1184- // ────────────────────────────────────────────────────────────────────────────
1150+ // p1_h P1/2 (2-MHz cycles) at first trigger
1151+ // d1 2-MHz cycles between the first trigger and the last NR33 write
1152+ // d2 2-MHz cycles between that NR33 write and the re-trigger
1153+ // p2_h P2/2 (2-MHz cycles) — the current period
11851154
11861155fn dmg_corrupt_offset ( p1_h : u32 , d1 : u32 , d2 : u32 , p2_h : u32 ) -> Option < usize > {
11871156 if p1_h == 0 || p2_h == 0 {
11881157 return None ;
11891158 }
11901159 let c1 = p1_h - 1 ;
11911160 let c2 = p2_h - 1 ;
1192-
11931161 let mut sc: u32 = c1 + 3 ;
11941162 let mut csi: u32 = 0 ;
1195-
11961163 // Phase 1.
11971164 if sc >= d1 {
11981165 sc -= d1;
@@ -1211,6 +1178,5 @@ fn dmg_corrupt_offset(p1_h: u32, d1: u32, d2: u32, p2_h: u32) -> Option<usize> {
12111178 csi = csi. wrapping_add ( rem / ( c2 + 1 ) ) & 0x1f ;
12121179 sc = c2. saturating_sub ( rem % ( c2 + 1 ) ) ;
12131180 }
1214-
12151181 if sc == 0 { Some ( ( ( csi as usize + 1 ) >> 1 ) & 0xf ) } else { None }
12161182}
0 commit comments