Skip to content

Commit cc69f07

Browse files
committed
add tick cyhcles
1 parent 7e8dc49 commit cc69f07

2 files changed

Lines changed: 83 additions & 1 deletion

File tree

src/domain/bus.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ impl Bus {
131131
pub fn step(&mut self, cycles: u32) {
132132
self.step_div(cycles);
133133
self.step_timer(cycles);
134+
self.mbc.tick(cycles);
134135
}
135136
}
136137

src/domain/mbc.rs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const EXT_RAM_BANK_SIZE: usize = 0x2000;
77
const MBC2_RAM_SIZE: usize = 512;
88
const MBC2_RAM_END: u16 = 0xA1FF;
99
const OPEN_BUS: u8 = 0xFF;
10+
const CYCLES_PER_SECOND: u32 = 4_194_304;
1011

1112
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1213
pub enum MbcError {
@@ -72,6 +73,12 @@ impl Mbc {
7273
MbcKind::Mbc5(mbc5) => mbc5.write8(cartridge, addr, value),
7374
}
7475
}
76+
77+
pub fn tick(&mut self, cycles: u32) {
78+
if let MbcKind::Mbc3(mbc3) = &mut self.kind {
79+
mbc3.tick(cycles);
80+
}
81+
}
7582
}
7683

7784
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -268,6 +275,54 @@ impl Rtc {
268275
RtcRegister::DayHigh => self.day_high = value,
269276
}
270277
}
278+
279+
fn tick_seconds(&mut self, seconds: u32) {
280+
if self.day_high & 0x40 != 0 {
281+
return;
282+
}
283+
284+
let mut remaining = seconds;
285+
while remaining > 0 {
286+
remaining -= 1;
287+
self.increment_one_second();
288+
}
289+
}
290+
291+
fn increment_one_second(&mut self) {
292+
self.seconds = self.seconds.wrapping_add(1);
293+
if self.seconds < 60 {
294+
return;
295+
}
296+
self.seconds = 0;
297+
self.minutes = self.minutes.wrapping_add(1);
298+
if self.minutes < 60 {
299+
return;
300+
}
301+
self.minutes = 0;
302+
self.hours = self.hours.wrapping_add(1);
303+
if self.hours < 24 {
304+
return;
305+
}
306+
self.hours = 0;
307+
308+
let day = self.day_counter();
309+
if day == 0x1FF {
310+
self.set_day_counter(0);
311+
self.day_high |= 0x80;
312+
} else {
313+
self.set_day_counter(day + 1);
314+
}
315+
}
316+
317+
fn day_counter(&self) -> u16 {
318+
let high = (self.day_high & 0x01) as u16;
319+
u16::from(self.day_low) | (high << 8)
320+
}
321+
322+
fn set_day_counter(&mut self, day: u16) {
323+
self.day_low = day as u8;
324+
self.day_high = (self.day_high & 0xFE) | ((day >> 8) as u8 & 0x01);
325+
}
271326
}
272327

273328
#[derive(Debug, Clone)]
@@ -277,6 +332,7 @@ struct Mbc3 {
277332
rtc_reg: Option<RtcRegister>,
278333
ram_enabled: bool,
279334
latch_pending: bool,
335+
rtc_counter: u32,
280336
rtc: Rtc,
281337
rtc_latched: Rtc,
282338
latched: bool,
@@ -297,6 +353,7 @@ impl Mbc3 {
297353
rtc_reg: None,
298354
ram_enabled: false,
299355
latch_pending: false,
356+
rtc_counter: 0,
300357
rtc,
301358
rtc_latched: rtc,
302359
latched: false,
@@ -373,6 +430,14 @@ impl Mbc3 {
373430
_ => {}
374431
}
375432
}
433+
434+
fn tick(&mut self, cycles: u32) {
435+
self.rtc_counter = self.rtc_counter.wrapping_add(cycles);
436+
while self.rtc_counter >= CYCLES_PER_SECOND {
437+
self.rtc_counter -= CYCLES_PER_SECOND;
438+
self.rtc.tick_seconds(1);
439+
}
440+
}
376441
}
377442

378443
#[derive(Debug, Clone)]
@@ -529,7 +594,7 @@ fn normalize_switchable_bank(bank: usize, bank_count: usize) -> usize {
529594

530595
#[cfg(test)]
531596
mod tests {
532-
use super::{Mbc, bank_count};
597+
use super::{CYCLES_PER_SECOND, Mbc, bank_count};
533598
use crate::domain::Cartridge;
534599
use crate::domain::cartridge::ROM_BANK_SIZE;
535600

@@ -656,6 +721,22 @@ mod tests {
656721
assert_eq!(mbc.read8(&cartridge, 0xA000), 0x25);
657722
}
658723

724+
#[test]
725+
fn mbc3_rtc_ticks_with_cycles() {
726+
let mut bytes = vec![0; ROM_BANK_SIZE * 2];
727+
bytes[0x0147] = 0x0F;
728+
bytes[0x0149] = 0x02;
729+
730+
let mut cartridge = Cartridge::from_bytes(bytes).expect("cartridge");
731+
let mut mbc = Mbc::new(&cartridge).expect("mbc");
732+
733+
mbc.write8(&mut cartridge, 0x0000, 0x0A);
734+
mbc.write8(&mut cartridge, 0x4000, 0x08);
735+
mbc.tick(CYCLES_PER_SECOND);
736+
737+
assert_eq!(mbc.read8(&cartridge, 0xA000), 1);
738+
}
739+
659740
#[test]
660741
fn mbc5_uses_9bit_rom_bank() {
661742
let mut bytes = vec![0; ROM_BANK_SIZE * 260];

0 commit comments

Comments
 (0)