1use crate::{
2 apu::Apu,
3 cartridge::Cartridge,
4 cpu::interrupts::InterruptControl,
5 joypad::JoypadController,
6 peripherals::{Cable, Joypad, Lcd, Speaker},
7 ppu::Ppu,
8 serial::SerialController,
9 timer::Timer,
10};
11
12pub struct Bus<L, S, J, C>
15where
16 L: Lcd,
17 S: Speaker,
18 J: Joypad,
19 C: Cable,
20{
21 cart: Cartridge,
22 ram: [u8; 0x2000],
23 hram: [u8; 0x7f],
24 joypad: JoypadController<J>,
25 serial: SerialController<C>,
26 timer: Timer,
27 apu: Apu<S>,
28 ppu: Ppu<L>,
29 pub interrupts: InterruptControl,
30}
31
32impl<L, S, J, C> Bus<L, S, J, C>
33where
34 L: Lcd,
35 S: Speaker,
36 J: Joypad,
37 C: Cable,
38{
39 pub fn new(rom: Vec<u8>, lcd: L, speaker: S, joypad: J, cable: C) -> Self {
42 let cart = Cartridge::new(rom)
43 .map_err(|e| log::error!("Failed to parse ROM header: {}", e))
44 .unwrap();
45 cart.log_header();
46 Self {
47 cart,
48 ram: [0; 0x2000],
49 hram: [0; 0x7f],
50 joypad: JoypadController::new(joypad),
51 serial: SerialController::new(cable),
52 timer: Timer::new(),
53 apu: Apu::new(speaker),
54 ppu: Ppu::new(lcd),
55 interrupts: InterruptControl::new(),
56 }
57 }
58
59 pub fn read(&self, addr: u16) -> u8 {
61 match addr {
62 0x0000..=0x7fff => self.cart.mbc.read_rom(addr),
64 0x8000..=0x9fff => self.ppu.fetcher.vram.read(addr - 0x8000),
66 0xa000..=0xbfff => self.cart.mbc.read_ram(addr - 0xa000),
68 0xc000..=0xdfff => self.ram[addr as usize - 0xc000],
70 0xe000..=0xfdff => {
71 log::debug!("Read from echo RAM at address {:#06x}", addr);
72 self.ram[addr as usize - 0xe000]
73 }
74 0xfe00..=0xfe9f => self.ppu.fetcher.oam.read(addr - 0xfe00),
76 0xff00 => self.joypad.p1.byte(),
79 0xff01 => self.serial.sb,
81 0xff02 => self.serial.sc,
82 0xff04 => (self.timer.div >> 8) as u8,
84 0xff05 => self.timer.tima,
85 0xff06 => self.timer.tma,
86 0xff07 => self.timer.tac.byte(),
87 0xff10..=0xff3f => self.apu.read(addr),
89 0xff40 => self.ppu.fetcher.lcdc.byte(),
91 0xff41 => self.ppu.stat.byte(),
92 0xff42 => self.ppu.fetcher.scy,
93 0xff43 => self.ppu.fetcher.scx,
94 0xff44 => self.ppu.fetcher.ly,
95 0xff45 => self.ppu.lyc,
96 0xff46 => 0xff,
97 0xff47 => self.ppu.fetcher.bgp.byte(),
98 0xff48 => self.ppu.fetcher.obp0.byte(),
99 0xff49 => self.ppu.fetcher.obp1.byte(),
100 0xff4a => self.ppu.fetcher.wy,
101 0xff4b => self.ppu.fetcher.wx,
102 0xff80..=0xfffe => self.hram[addr as usize - 0xff80],
104 0xff0f => self.interrupts.flags.byte(),
106 0xffff => self.interrupts.enable.byte(),
107 _ => {
108 log::debug!("Read from unmapped address {:#06x}", addr);
109 0xff
110 }
111 }
112 }
113
114 pub fn write(&mut self, addr: u16, val: u8) {
116 match addr {
117 0x0000..=0x7fff => self.cart.mbc.write_rom(addr, val),
119 0x8000..=0x9fff => self.ppu.fetcher.vram.write(addr - 0x8000, val),
121 0xa000..=0xbfff => self.cart.mbc.write_ram(addr - 0xa000, val),
123 0xc000..=0xdfff => self.ram[addr as usize - 0xc000] = val,
125 0xe000..=0xfdff => {
126 self.ram[addr as usize - 0xe000] = val;
127 log::debug!("Write to echo RAM at address {:#06x}", addr);
128 }
129 0xfe00..=0xfe9f => self.ppu.fetcher.oam.write(addr - 0xfe00, val),
131 0xff00 => self.joypad.p1.set_byte(val),
134 0xff01 => self.serial.sb = val,
136 0xff02 => self.serial.sc = val,
137 0xff04 => self.timer.div = 0,
139 0xff05 => self.timer.tima = val,
140 0xff06 => self.timer.tma = val,
141 0xff07 => self.timer.tac.set_byte(val),
142 0xff10..=0xff3f => self.apu.write(addr, val),
144 0xff40 => self.ppu.fetcher.lcdc.set_byte(val),
146 0xff41 => self.ppu.stat.set_byte(val),
147 0xff42 => self.ppu.fetcher.scy = val,
148 0xff43 => self.ppu.fetcher.scx = val,
149 0xff44 => self.ppu.fetcher.ly = val,
150 0xff45 => self.ppu.lyc = val,
151 0xff46 => self.ppu.dma.start(val),
152 0xff47 => self.ppu.fetcher.bgp.set_byte(val),
153 0xff48 => self.ppu.fetcher.obp0.set_byte(val),
154 0xff49 => self.ppu.fetcher.obp1.set_byte(val),
155 0xff4a => self.ppu.fetcher.wy = val,
156 0xff4b => self.ppu.fetcher.wx = val,
157 0xff80..=0xfffe => self.hram[addr as usize - 0xff80] = val,
159 0xff0f => self.interrupts.flags.set_byte(val),
161 0xffff => self.interrupts.enable.set_byte(val),
162 _ => log::debug!("Write to unmapped address {:#06x}", addr),
163 }
164 }
165
166 pub fn io_step(&mut self) {
169 self.dma_step();
170
171 let ints = &mut self.interrupts.flags;
172 self.joypad.step(ints);
173 self.ppu.step(ints);
174 self.apu.step();
175 self.serial.step(ints);
176 self.timer.step(ints);
177 }
178
179 fn dma_step(&mut self) {
181 if self.ppu.dma.active {
182 let val = self.read(self.ppu.dma.src());
183 self.write(self.ppu.dma.dst(), val);
184 self.ppu.dma.step();
185 }
186 }
187}