Compare commits

..

No commits in common. "aa22e93049a9c77cf5442738fee6c5a89d886b4d" and "a77d0a0f62aa62032a3bc21c7f37f25e3775d5b1" have entirely different histories.

7 changed files with 41 additions and 40 deletions

View File

@ -164,7 +164,8 @@ impl Apu {
if self.ctrl.enabled { if self.ctrl.enabled {
// Frame Sequencer reset to Step 0 // Frame Sequencer reset to Step 0
// TODO: With the current implementation of the frame sequencer, what does this even mean? // TODO: With the current implementation of the frame sequencer,
// what does this even mean?
// Square Duty units are reset to first step // Square Duty units are reset to first step
self.ch1.duty_pos = 0; self.ch1.duty_pos = 0;
@ -180,6 +181,8 @@ impl Apu {
} }
fn reset(&mut self) { fn reset(&mut self) {
// TODO: Clear readable sound registers
self.ch1.sweep = Default::default(); self.ch1.sweep = Default::default();
self.ch1.duty = Default::default(); self.ch1.duty = Default::default();
self.ch1.envelope = Default::default(); self.ch1.envelope = Default::default();
@ -423,6 +426,7 @@ impl Channel1 {
} }
if self.freq_timer == 0 { if self.freq_timer == 0 {
// TODO: Why is this 2048?
self.freq_timer = (2048 - self.frequency()) * 4; self.freq_timer = (2048 - self.frequency()) * 4;
self.duty_pos = (self.duty_pos + 1) % 8; self.duty_pos = (self.duty_pos + 1) % 8;
} }
@ -568,6 +572,7 @@ impl Channel2 {
} }
if self.freq_timer == 0 { if self.freq_timer == 0 {
// TODO: Why is this 2048?
self.freq_timer = (2048 - self.frequency()) * 4; self.freq_timer = (2048 - self.frequency()) * 4;
self.duty_pos = (self.duty_pos + 1) % 8; self.duty_pos = (self.duty_pos + 1) % 8;
} }

View File

@ -178,7 +178,7 @@ pub(crate) mod ch4 {
pub struct Frequency(u8); pub struct Frequency(u8);
impl Debug; impl Debug;
_initial, _: 7; _initial, _: 7;
_length_disable, _: 6; _length_disable, _: 6; // TODO: same as FrequencyHigh, figure out what this is
} }
impl Frequency { impl Frequency {
@ -224,7 +224,7 @@ pub(crate) mod common {
pub struct FrequencyHigh(u8); pub struct FrequencyHigh(u8);
impl Debug; impl Debug;
_initial, _: 7; _initial, _: 7;
_length_disable, _: 6; _length_disable, _: 6; // TODO: Figure out what the hell this is
pub freq_bits, set_freq_bits: 2, 0; pub freq_bits, set_freq_bits: 2, 0;
} }
@ -342,7 +342,7 @@ pub(crate) mod common {
pub struct SoundDuty(u8); pub struct SoundDuty(u8);
impl Debug; impl Debug;
from into WavePattern, _wave_pattern, _: 7, 6; from into WavePattern, _wave_pattern, _: 7, 6;
_sound_length, _: 5, 0; _sound_length, _: 5, 0; // TODO: Getter only used if bit 6 in NR14 is set
} }
impl SoundDuty { impl SoundDuty {

View File

@ -240,6 +240,7 @@ impl BusIo for Bus {
0x49 => self.ppu.monochrome.obj_palette_1.into(), 0x49 => self.ppu.monochrome.obj_palette_1.into(),
0x4A => self.ppu.pos.window_y, 0x4A => self.ppu.pos.window_y,
0x4B => self.ppu.pos.window_x, 0x4B => self.ppu.pos.window_x,
0x4D => 0xFF, // TODO: CGB Specific Register
_ => { _ => {
eprintln!("Read 0xFF from unused IO register {:#06X}.", addr); eprintln!("Read 0xFF from unused IO register {:#06X}.", addr);
0xFF 0xFF
@ -311,7 +312,7 @@ impl BusIo for Bus {
_ => {} _ => {}
} }
} }
0xFEA0..=0xFEFF => {} // FIXME: As far as I know, writes to here do nothing. 0xFEA0..=0xFEFF => {} // TODO: As far as I know, writes to here do nothing.
0xFF00..=0xFF7F => { 0xFF00..=0xFF7F => {
// IO Registers // IO Registers

View File

@ -114,7 +114,10 @@ impl Cartridge {
} }
fn find_mbc(memory: &[u8]) -> MBCKind { fn find_mbc(memory: &[u8]) -> MBCKind {
match memory[MBC_TYPE_ADDRESS] { let id = memory[MBC_TYPE_ADDRESS];
// TODO: Refactor this to match the other enums in this module
match id {
0x00 => MBCKind::None, 0x00 => MBCKind::None,
0x01 => MBCKind::MBC1, 0x01 => MBCKind::MBC1,
0x02 => MBCKind::MBC1, 0x02 => MBCKind::MBC1,
@ -122,7 +125,7 @@ impl Cartridge {
0x19 => MBCKind::MBC5, 0x19 => MBCKind::MBC5,
0x13 => MBCKind::MBC3WithBattery, 0x13 => MBCKind::MBC3WithBattery,
0x11 => MBCKind::MBC3, 0x11 => MBCKind::MBC3,
id => unimplemented!("id {:#04X} is an unsupported MBC", id), _ => unimplemented!("id {:#04X} is an unsupported MBC", id),
} }
} }
} }

View File

@ -14,6 +14,8 @@ pub struct Cpu {
reg: Registers, reg: Registers,
flags: Flags, flags: Flags,
ime: ImeState, ime: ImeState,
// TODO: Merge halted and state properties
halted: Option<HaltKind>,
state: State, state: State,
} }
@ -43,34 +45,24 @@ impl Cpu {
}) })
} }
pub(crate) fn ime(&self) -> ImeState { pub(crate) fn ime(&self) -> &ImeState {
self.ime &self.ime
} }
pub(crate) fn set_ime(&mut self, state: ImeState) { pub(crate) fn set_ime(&mut self, state: ImeState) {
self.ime = state; self.ime = state;
} }
pub(crate) fn halt_cpu(&mut self, kind: HaltKind) { pub(crate) fn halt(&mut self, state: HaltKind) {
self.state = State::Halt(kind); self.halted = Some(state);
} }
fn resume_execution(&mut self) { fn resume(&mut self) {
self.state = State::Execute; self.halted = None;
} }
pub(crate) fn is_halted(&self) -> bool { pub(crate) fn halted(&self) -> Option<HaltKind> {
match self.state { self.halted
State::Halt(_) => true,
_ => false,
}
}
pub(crate) fn halt_kind(&self) -> Option<HaltKind> {
match self.state {
State::Halt(kind) => Some(kind),
_ => None,
}
} }
pub fn load_cartridge(&mut self, path: &str) -> std::io::Result<()> { pub fn load_cartridge(&mut self, path: &str) -> std::io::Result<()> {
@ -127,7 +119,7 @@ impl Cpu {
return elapsed; return elapsed;
} }
if let Some(kind) = self.halt_kind() { if let Some(kind) = self.halted() {
use HaltKind::*; use HaltKind::*;
self.bus.clock(); self.bus.clock();
@ -200,7 +192,7 @@ impl Cpu {
let enable = self.int_enable(); let enable = self.int_enable();
// TODO: Ensure that this behaviour is correct // TODO: Ensure that this behaviour is correct
if self.is_halted() { if self.halted.is_some() {
// When we're here either a HALT with IME set or // When we're here either a HALT with IME set or
// a HALT with IME not set and No pending Interrupts was called // a HALT with IME not set and No pending Interrupts was called
@ -209,7 +201,7 @@ impl Cpu {
// nothing actually needs to be added here. This is just documentation // nothing actually needs to be added here. This is just documentation
// since it's a bit weird why nothing is being done // since it's a bit weird why nothing is being done
self.resume_execution(); self.resume();
} }
} }
@ -272,7 +264,7 @@ impl Cpu {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum State { enum State {
Execute, Execute,
Halt(HaltKind), // Halt,
// Stop, // Stop,
} }

View File

@ -590,12 +590,12 @@ impl Instruction {
// HALT | Enter CPU low power consumption mode until interrupt occurs // HALT | Enter CPU low power consumption mode until interrupt occurs
use HaltKind::*; use HaltKind::*;
let kind = match cpu.ime() { let kind = match *cpu.ime() {
ImeState::Enabled => ImeEnabled, ImeState::Enabled => ImeEnabled,
_ if cpu.int_request() & cpu.int_enable() != 0 => SomePending, _ if cpu.int_request() & cpu.int_enable() != 0 => SomePending,
_ => NonePending, _ => NonePending,
}; };
cpu.halt_cpu(kind); cpu.halt(kind);
Cycle::new(4) Cycle::new(4)
} }
Instruction::ADC(source) => match source { Instruction::ADC(source) => match source {

View File

@ -63,16 +63,16 @@ fn main() -> Result<()> {
}; };
// Initialize Audio // Initialize Audio
// let spsc: AudioSPSC<f32> = Default::default(); let spsc: AudioSPSC<f32> = Default::default();
// let (prod, cons) = spsc.init(); let (prod, cons) = spsc.init();
// let (_stream, stream_handle) = OutputStream::try_default().expect("Initialized Audio"); let (_stream, stream_handle) = OutputStream::try_default().expect("Initialized Audio");
// let sink = Sink::try_new(&stream_handle)?; let sink = Sink::try_new(&stream_handle)?;
// sink.append(cons); sink.append(cons);
// game_boy.apu_mut().set_producer(prod); game_boy.apu_mut().set_producer(prod);
// std::thread::spawn(move || { std::thread::spawn(move || {
// sink.sleep_until_end(); sink.sleep_until_end();
// }); });
let mut start = Instant::now(); let mut start = Instant::now();
let frame_time = Duration::from_secs_f64(1.0 / 59.73); // 59.73 Hz on Host let frame_time = Duration::from_secs_f64(1.0 / 59.73); // 59.73 Hz on Host