diff --git a/src/nes/apu.rs b/src/nes/apu.rs index b27f950..2ec750c 100644 --- a/src/nes/apu.rs +++ b/src/nes/apu.rs @@ -3,12 +3,12 @@ use super::system::*; #[derive(Copy, Clone)] pub struct PulseSound { // $4000 / $4004 - /// 0-100でDuty Cycleを設定する - pub dutyCycle: u8, + /// Duty Cycleを設定する + pub dutyCycle: f32, /// 再生時間カウンタ有効 - pub lengthCounterHalt: bool, + pub isLengthCounterHalt: bool, /// 音響選択 - pub constantVolume: bool, + pub isConstantVolume: bool, /// 音量値 4bit pub volume: u8, @@ -18,7 +18,7 @@ pub struct PulseSound { /// 周波数スイープ値 pub sweepPeriod: u8, /// 周波数スイープの方向(add/sub) - pub isSweepPositive: bool, + pub isSweepNegative: bool, /// 周波数範囲 pub sweepShift: u8, @@ -31,13 +31,13 @@ pub struct PulseSound { impl Default for PulseSound { fn default() -> Self { Self { - dutyCycle: 0, - lengthCounterHalt: false, - constantVolume: false, + dutyCycle: 0.0, + isLengthCounterHalt: false, + isConstantVolume: false, volume: 0, isSweepEnable: false, sweepPeriod: 0, - isSweepPositive: false, + isSweepNegative: false, sweepShift: 0, timerValue: 0, lengthCounterLoad: 0, @@ -49,7 +49,7 @@ impl Default for PulseSound { pub struct TriangleSound { // $4008 /// 再生時間カウンタ有効 - pub lengthCounterHalt: bool, + pub isLengthCounterHalt: bool, /// 再生時間カウンタ値 pub counterValue: u8, // $400a, $400b @@ -62,7 +62,7 @@ pub struct TriangleSound { impl Default for TriangleSound { fn default() -> Self { Self { - lengthCounterHalt: false, + isLengthCounterHalt: false, counterValue: 0, timerValue: 0, lengthCounterLoad: 0, @@ -76,7 +76,7 @@ pub struct NoiseSound { /// 再生時間カウンタ有効 pub lengthCounterHalt: bool, /// 音響選択 - pub constantVolume: bool, + pub isConstantVolume: bool, /// 音量値 4bit pub volume: u8, // $400E @@ -93,7 +93,7 @@ impl Default for NoiseSound { fn default() -> Self { Self { lengthCounterHalt: false, - constantVolume: false, + isConstantVolume: false, volume: 0, isNoiseTypeLoop: false, noisePeriod: 0, diff --git a/src/nes/system_apu_reg.rs b/src/nes/system_apu_reg.rs index d023a15..51a608b 100644 --- a/src/nes/system_apu_reg.rs +++ b/src/nes/system_apu_reg.rs @@ -9,7 +9,40 @@ pub const APU_DMC_OFFSET: usize = 0x10; pub const APU_STATUS_OFFSET: usize = 0x15; pub const APU_FRAMECOUNTER_OFFSET: usize = 0x15; -// APU & I/O(PAD) Register Implement +/// APU & I/O(PAD) Register Implement +/// APUのみ(DMAはsystem_ppu_reg.rs, padはレジスタの変数を使わない) +/// 固定小数点演算が入るものは、別途関数で計算する(定数を返すだけなら構わない) impl System { + /// Puluse波の設定を取得します + /// `index` - 0 or 1 + pub fn read_apu_pulse_config(&self, index: u8) -> PulseSound { + let mut dst = PulseSound::default(); + debug_assert!(index < 2); + let base_offset = if index == 0 { APU_PULSE_1_OFFSET } else { APU_PULSE_2_OFFSET }; + // 順番に読んで値を決めるだけ + dst.dutyCycle = match (self.io_reg[base_offset + 0] >> 6) & 0x03 { + 0 => 87.5, + 1 => 75.0, + 2 => 50.0, + 3 => 25.0, + _ => panic!("invalid pulse dutyCycle: {}", self.io_reg[base_offset + 0]), + }; + // $4000 DDLCVVVV + dst.isLengthCounterHalt = (self.io_reg[base_offset + 0] & 0x20) == 0x20; + dst.isConstantVolume = (self.io_reg[base_offset + 0] & 0x10) == 0x10; + dst.volume = self.io_reg[base_offset + 0] & 0x0f; + // $4001 EPPPNSSS + dst.isSweepEnable = (self.io_reg[base_offset + 1] & 0x80) == 0x80; + dst.sweepPeriod = (self.io_reg[base_offset + 1] & 0x70) >> 4; + dst.isSweepNegative = (self.io_reg[base_offset + 1] & 0x04) == 0x04; + dst.sweepShift = self.io_reg[base_offset + 1] & 0x07; + // $4002 TTTTTTTT(timer lower) + // $4003 LLLLLTTT(timer Upper) + dst.timerValue = u16::from(self.io_reg[base_offset + 2]) | + (u16::from(self.io_reg[base_offset + 3] & 0x07) << 8); + dst.lengthCounterLoad = (self.io_reg[base_offset + 3] & 0xf8) >> 3; + + dst + } }