fix: convert sound.rs structs to bitfields

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-03-15 21:16:11 -05:00
parent 61fd63bb45
commit 8989d3f1d7
4 changed files with 211 additions and 138 deletions

7
Cargo.lock generated
View File

@ -61,6 +61,12 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]]
name = "bitfield"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.2.1" version = "1.2.1"
@ -465,6 +471,7 @@ name = "gb"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bitfield",
"pixels", "pixels",
"winit", "winit",
"winit_input_helper", "winit_input_helper",

View File

@ -8,6 +8,7 @@ edition = "2018"
[dependencies] [dependencies]
anyhow = "^1.0" anyhow = "^1.0"
bitfield = "0.13.2"
pixels = "^0.2" pixels = "^0.2"
winit = "^0.24" winit = "^0.24"
winit_input_helper = "^0.9" winit_input_helper = "^0.9"

View File

@ -120,9 +120,9 @@ impl Bus {
0xFF0F => self.interrupt.flag.into(), 0xFF0F => self.interrupt.flag.into(),
0xFF11 => self.sound.ch1.sound_duty.into(), 0xFF11 => self.sound.ch1.sound_duty.into(),
0xFF12 => self.sound.ch1.vol_envelope.into(), 0xFF12 => self.sound.ch1.vol_envelope.into(),
0xFF14 => self.sound.ch1.freq.get_hi(), 0xFF14 => self.sound.ch1.freq_hi.into(),
0xFF24 => self.sound.control.channel.into(), 0xFF24 => self.sound.control.channel.into(),
0xFF25 => self.sound.control.select.into(), 0xFF25 => self.sound.control.output.into(),
0xFF26 => self.sound.control.status.into(), 0xFF26 => self.sound.control.status.into(),
0xFF40 => self.ppu.lcd_control.into(), 0xFF40 => self.ppu.lcd_control.into(),
0xFF41 => self.ppu.stat.into(), 0xFF41 => self.ppu.stat.into(),
@ -200,10 +200,10 @@ impl Bus {
0xFF0F => self.interrupt.flag = byte.into(), 0xFF0F => self.interrupt.flag = byte.into(),
0xFF11 => self.sound.ch1.sound_duty = byte.into(), 0xFF11 => self.sound.ch1.sound_duty = byte.into(),
0xFF12 => self.sound.ch1.vol_envelope = byte.into(), 0xFF12 => self.sound.ch1.vol_envelope = byte.into(),
0xFF13 => self.sound.ch1.freq.set_lo(byte), 0xFF13 => self.sound.ch1.freq_lo = byte.into(),
0xFF14 => self.sound.ch1.freq.set_hi(byte), 0xFF14 => self.sound.ch1.freq_hi = byte.into(),
0xFF24 => self.sound.control.channel = byte.into(), 0xFF24 => self.sound.control.channel = byte.into(),
0xFF25 => self.sound.control.select = byte.into(), 0xFF25 => self.sound.control.output = byte.into(),
0xFF26 => self.sound.control.status = byte.into(), // FIXME: Should we control which bytes are written to here? 0xFF26 => self.sound.control.status = byte.into(), // FIXME: Should we control which bytes are written to here?
0xFF40 => self.ppu.lcd_control = byte.into(), 0xFF40 => self.ppu.lcd_control = byte.into(),
0xFF41 => self.ppu.stat = byte.into(), 0xFF41 => self.ppu.stat = byte.into(),

View File

@ -1,5 +1,5 @@
use crate::instruction::Cycles; use crate::instruction::Cycles;
use bitfield::bitfield;
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct Sound { pub struct Sound {
pub control: SoundControl, pub control: SoundControl,
@ -15,16 +15,74 @@ impl Sound {
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct SoundControl { pub struct SoundControl {
pub channel: ChannelControl, pub channel: ChannelControl,
pub select: SoundOutputSelect, pub output: SoundOutput,
pub status: SoundStatus, pub status: SoundStatus,
} }
#[derive(Debug, Clone, Copy, Default)] // TODO: What to do about the separation of freq bits
pub struct Frequency { // across multiple registers?
initial: bool, bitfield! {
freq_type: FrequencyType, pub struct FrequencyHigh(u8);
lo: u8, // Bottom 8 bits impl Debug;
hi: u8, // Top 3 bits (11 bits total) _, initial: 7;
from into FrequencyType, get_freq_type, set_freq_type: 6;
_, set_freq_high_bits: 2, 0;
}
impl Copy for FrequencyHigh {}
impl Clone for FrequencyHigh {
fn clone(&self) -> Self {
*self
}
}
impl Default for FrequencyHigh {
fn default() -> Self {
Self(0)
}
}
impl From<u8> for FrequencyHigh {
fn from(byte: u8) -> Self {
Self(byte)
}
}
impl From<FrequencyHigh> for u8 {
fn from(duty: FrequencyHigh) -> Self {
duty.0
}
}
bitfield! {
pub struct FrequencyLow(u8);
impl Debug;
pub _, set_freq_bits: 7, 0;
}
impl Copy for FrequencyLow {}
impl Clone for FrequencyLow {
fn clone(&self) -> Self {
*self
}
}
impl Default for FrequencyLow {
fn default() -> Self {
Self(0)
}
}
impl From<u8> for FrequencyLow {
fn from(byte: u8) -> Self {
Self(byte)
}
}
pub fn get_11bit_freq(low: &FrequencyLow, high: FrequencyHigh) -> u16 {
let high_bits = high.0 & 0b111;
(low.0 as u16) << 8 | ((high_bits as u16) << 4)
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -49,61 +107,38 @@ impl Default for FrequencyType {
} }
} }
impl Frequency { bitfield! {
fn get_11bit_freq(&self) -> u16 { pub struct SoundStatus(u8);
(self.hi as u16) << 8 | self.lo as u16 impl Debug;
} all_enabled, set_all_enabled: 7;
sound_4, _: 3;
sound_3, _: 2;
sound_2, _: 1;
sound_1, _: 0;
}
pub fn set_lo(&mut self, byte: u8) { impl Copy for SoundStatus {}
self.lo = byte; impl Clone for SoundStatus {
} fn clone(&self) -> Self {
*self
pub fn get_lo(&self) -> u8 {
self.lo
}
pub fn set_hi(&mut self, byte: u8) {
*self = Self {
initial: byte >> 7 == 0x01,
freq_type: ((byte >> 6) & 0x01).into(),
lo: self.lo,
hi: byte & 0x07,
};
}
pub fn get_hi(&self) -> u8 {
(self.initial as u8) << 7 | (self.freq_type as u8) << 6 | self.hi
} }
} }
#[derive(Debug, Clone, Copy, Default)] impl Default for SoundStatus {
pub struct SoundStatus { fn default() -> Self {
pub all_enabled: bool, // You can actually write to this one. Self(0)
sound_4: bool, }
sound_3: bool,
sound_2: bool,
sound_1: bool,
} }
impl From<u8> for SoundStatus { impl From<u8> for SoundStatus {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
Self { Self(byte)
all_enabled: (byte >> 7) & 0x01 == 0x01,
sound_4: (byte >> 3) & 0x01 == 0x01,
sound_3: (byte >> 2) & 0x01 == 0x01,
sound_2: (byte >> 1) & 0x01 == 0x01,
sound_1: (byte >> 0) & 0x01 == 0x01,
}
} }
} }
impl From<SoundStatus> for u8 { impl From<SoundStatus> for u8 {
fn from(status: SoundStatus) -> Self { fn from(duty: SoundStatus) -> Self {
(status.all_enabled as u8) << 7 duty.0
| (status.sound_4 as u8) << 3
| (status.sound_3 as u8) << 2
| (status.sound_2 as u8) << 1
| (status.sound_1 as u8) << 0
} }
} }
@ -111,33 +146,40 @@ impl From<SoundStatus> for u8 {
pub struct Channel1 { pub struct Channel1 {
pub sound_duty: SoundDuty, pub sound_duty: SoundDuty,
pub vol_envelope: VolumeEnvelope, pub vol_envelope: VolumeEnvelope,
pub freq: Frequency, pub freq_hi: FrequencyHigh,
pub freq_lo: FrequencyLow,
} }
#[derive(Debug, Clone, Copy, Default)] bitfield! {
pub struct VolumeEnvelope { pub struct VolumeEnvelope(u8);
init_vol: u8, impl Debug;
direction: EnvelopeDirection, init_vol, set_init_vol: 7, 4;
sweep_count: u8, from into EnvelopeDirection, direction, set_direction: 3;
sweep_count, set_sweep_count: 2, 0;
}
impl Copy for VolumeEnvelope {}
impl Clone for VolumeEnvelope {
fn clone(&self) -> Self {
*self
}
}
impl Default for VolumeEnvelope {
fn default() -> Self {
Self(0)
}
} }
impl From<u8> for VolumeEnvelope { impl From<u8> for VolumeEnvelope {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
Self { Self(byte)
init_vol: byte >> 4, // Bit 7 -> 4
direction: ((byte >> 3) & 0x01).into(), // Bit 3
sweep_count: byte & 0x07, // Bits 2 -> 0
}
} }
} }
impl From<VolumeEnvelope> for u8 { impl From<VolumeEnvelope> for u8 {
fn from(envelope: VolumeEnvelope) -> Self { fn from(duty: VolumeEnvelope) -> Self {
let dir_bit: u8 = envelope.direction as u8; duty.0
let mut byte = envelope.init_vol << 4;
byte |= dir_bit << 3;
byte |= envelope.sweep_count;
byte
} }
} }
@ -166,47 +208,66 @@ impl Default for EnvelopeDirection {
} }
} }
#[derive(Debug, Clone, Copy, Default)] bitfield! {
pub struct SoundDuty { pub struct SoundDuty(u8);
wave_pattern: WaveDuty, impl Debug;
sound_length: u8, // from into WavePattern, wave_pattern, set_wave_pattern: 7, 6;
_, set_sound_length: 5, 0; // TODO: Getter only used if bit 6 in NR14 is set
}
impl Copy for SoundDuty {}
impl Clone for SoundDuty {
fn clone(&self) -> Self {
*self
}
}
impl Default for SoundDuty {
fn default() -> Self {
Self(0)
}
} }
impl From<u8> for SoundDuty { impl From<u8> for SoundDuty {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
let pattern = byte >> 6; // Get bytes 7 and 6 Self(byte)
let sound_length = byte & 0x3F; // Clear bytes 7 and 6
SoundDuty {
wave_pattern: pattern.into(),
sound_length,
}
} }
} }
impl From<SoundDuty> for u8 { impl From<SoundDuty> for u8 {
fn from(duty: SoundDuty) -> Self { fn from(duty: SoundDuty) -> Self {
let mut byte: u8 = duty.wave_pattern as u8; duty.0
byte = (byte << 6) | duty.sound_length; }
byte }
impl From<WavePattern> for u8 {
fn from(pattern: WavePattern) -> Self {
use WavePattern::*;
match pattern {
OneEighth => 0b00,
OneQuarter => 0b01,
OneHalf => 0b10,
ThreeQuarters => 0b11,
}
} }
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum WaveDuty { pub enum WavePattern {
OneEighth = 0, // 12.5% ( _-------_-------_------- ) OneEighth = 0, // 12.5% ( _-------_-------_------- )
OneQuarter = 1, // 25% ( __------__------__------ ) OneQuarter = 1, // 25% ( __------__------__------ )
OneHalf = 2, // 50% ( ____----____----____---- ) (normal) OneHalf = 2, // 50% ( ____----____----____---- ) (normal)
ThreeQuarters = 3, // 75% ( ______--______--______-- ) ThreeQuarters = 3, // 75% ( ______--______--______-- )
} }
impl Default for WaveDuty { impl Default for WavePattern {
fn default() -> Self { fn default() -> Self {
Self::OneEighth // Rationale: OneEighth is 0x00 Self::OneEighth // Rationale: OneEighth is 0x00
} }
} }
impl From<u8> for WaveDuty { impl From<u8> for WavePattern {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
match byte { match byte {
0b00 => Self::OneEighth, 0b00 => Self::OneEighth,
@ -218,70 +279,74 @@ impl From<u8> for WaveDuty {
} }
} }
#[derive(Debug, Clone, Copy, Default)] bitfield! {
pub struct SoundOutputSelect { pub struct SoundOutput(u8);
pub snd4_term2: bool, impl Debug;
pub snd3_term2: bool, snd4_so2, set_snd4_so2: 7;
pub snd2_term2: bool, snd3_so2, set_snd3_so2: 6;
pub snd1_term2: bool, snd2_so2, set_snd2_so2: 5;
pub snd4_term1: bool, snd1_so2, set_snd1_so2: 4;
pub snd3_term1: bool, snd4_so1, set_snd4_so1: 3;
pub snd2_term1: bool, snd3_so1, set_snd3_so1: 2;
pub snd1_term1: bool, snd2_so1, set_snd2_so1: 1;
snd1_so1, set_snd1_so1: 0;
} }
impl From<SoundOutputSelect> for u8 { impl Copy for SoundOutput {}
fn from(select: SoundOutputSelect) -> Self { impl Clone for SoundOutput {
(select.snd4_term2 as u8) << 7 fn clone(&self) -> Self {
| (select.snd3_term2 as u8) << 6 *self
| (select.snd2_term2 as u8) << 5
| (select.snd1_term2 as u8) << 4
| (select.snd4_term1 as u8) << 3
| (select.snd3_term1 as u8) << 2
| (select.snd2_term1 as u8) << 1
| (select.snd1_term1 as u8)
} }
} }
impl From<u8> for SoundOutputSelect { impl Default for SoundOutput {
fn default() -> Self {
Self(0)
}
}
impl From<u8> for SoundOutput {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
Self { Self(byte)
snd4_term2: byte >> 7 == 0x01,
snd3_term2: (byte >> 6) & 0x01 == 0x01,
snd2_term2: (byte >> 5) & 0x01 == 0x01,
snd1_term2: (byte >> 4) & 0x01 == 0x01,
snd4_term1: (byte >> 3) & 0x01 == 0x01,
snd3_term1: (byte >> 2) & 0x01 == 0x01,
snd2_term1: (byte >> 1) & 0x01 == 0x01,
snd1_term1: byte & 0x01 == 0x01,
}
} }
} }
#[derive(Debug, Clone, Copy, Default)] impl From<SoundOutput> for u8 {
pub struct ChannelControl { fn from(duty: SoundOutput) -> Self {
vin_to_term2: bool, duty.0
term2_level: u8, }
vin_to_term1: bool, }
term1_level: u8,
bitfield! {
pub struct ChannelControl(u8);
impl Debug;
vin_so2, set_vin_so2: 7;
so2_level, set_so2_level: 6, 4;
vin_so1, set_vin_so1: 3;
so1_level, set_so1_level: 2, 0;
}
impl Copy for ChannelControl {}
impl Clone for ChannelControl {
fn clone(&self) -> Self {
*self
}
}
impl Default for ChannelControl {
fn default() -> Self {
Self(0)
}
} }
impl From<u8> for ChannelControl { impl From<u8> for ChannelControl {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
Self { Self(byte)
vin_to_term2: byte >> 7 == 0x01, // Get 7th bit
term2_level: (byte & 0x7F) >> 4, // Clear 7th then get 6 -> 4th bit
vin_to_term1: (byte >> 3) & 0x01 == 0x01,
term1_level: byte & 0x07, // Bits 2 -> 0
}
} }
} }
impl From<ChannelControl> for u8 { impl From<ChannelControl> for u8 {
fn from(control: ChannelControl) -> Self { fn from(duty: ChannelControl) -> Self {
(control.vin_to_term1 as u8) << 7 duty.0
| (control.term2_level as u8) << 4
| (control.vin_to_term1 as u8) << 3
| control.term1_level as u8
} }
} }