diff --git a/src/cpu.rs b/src/cpu.rs index de2e0ba..93cb73d 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -1050,7 +1050,9 @@ impl CPU { // ADC 0x88 ... 0x8F => { let reg_id = (instruction - 0x88) as usize; - println!("ADC {}", REG_NAMES[reg_id]); + if self.debug { + println!("ADC {}", REG_NAMES[reg_id]); + } let old = self.regs[REG_A]; let mut new = old.wrapping_add(self.get_8bit_reg(reg_id)); diff --git a/src/interconnect.rs b/src/interconnect.rs index 36ffaed..1c725be 100644 --- a/src/interconnect.rs +++ b/src/interconnect.rs @@ -27,7 +27,10 @@ pub struct Interconnect { serial: serial::Serial, timer: timer::Timer, - + vram_dma_source_high: u8, + vram_dma_source_low: u8, + vram_dma_destination_high: u8, + vram_dma_destination_low: u8, } impl Interconnect { @@ -37,7 +40,7 @@ impl Interconnect { cartridge: cartridge::Cartridge::new(rom), ram: vec![0; WRAM_SIZE].into_boxed_slice(), hiram: vec![0; HIRAM_SIZE].into_boxed_slice(), - wram_bank: 0, + wram_bank: 1, sound: sound::Sound::new(), display: display::Display::new(), // Refactor those @@ -48,12 +51,17 @@ impl Interconnect { timer: timer::Timer::new(), serial: serial::Serial::new(), + vram_dma_source_high: 0, + vram_dma_source_low: 0, + vram_dma_destination_high: 0, + vram_dma_destination_low: 0, } } // Somehow we need different timers for this. pub fn tick(&mut self, cycles: u8) { self.display.tick(cycles as u16 * 4); + self.timer.tick(cycles as u16 * 4); if self.display.vblank_interrupt() { self.interrupt_request_flags |= INTERRUPT_DISPLAY_VBLANK; @@ -108,6 +116,14 @@ impl Interconnect { 0xFF50 => { self.disable_bootrom }, + 0xFF51 => self.vram_dma_source_high, + 0xFF52 => self.vram_dma_source_low, + 0xFF53 => self.vram_dma_destination_high, + 0xFF54 => self.vram_dma_destination_low, + 0xFF55 => { + println!("Read from 0xFF55 (DMA length/mode/start) not fully supported"); + 0xFF + } 0xFF56 => { self.infrared_com_port }, @@ -163,7 +179,7 @@ impl Interconnect { self.display.write_byte(addr, val); }, 0xFF46 => { - println!("DMA transfer: "); + println!("OAM DMA transfer: "); for x in 0x00 .. 0x9F { let dma_b = self.read_byte(((val as u16) << 8) | x); self.write_byte(0xFE00 | x, dma_b); @@ -175,10 +191,30 @@ impl Interconnect { println!("Disabling boot rom."); self.disable_bootrom = val; }, + 0xFF51 => self.vram_dma_source_high = val, + 0xFF52 => self.vram_dma_source_low = val, + 0xFF53 => self.vram_dma_destination_high = val, + 0xFF54 => self.vram_dma_destination_low = val, + 0xFF55 => { + let src: u16 = ((self.vram_dma_source_high as u16) << 8) | self.vram_dma_source_low as u16; + let dst: u16 = ((self.vram_dma_destination_high as u16) << 8) | self.vram_dma_destination_low as u16; + println!("VRAM DMA transfer from {:04X} to {:04X}; {:02X}", src, dst, val); + let len: u16 = ((val & 0x7F) + 1) as u16 * 0x10 - 1; + for i in 0..len { + let v = self.read_byte(src.wrapping_add(i)); + self.write_byte(dst.wrapping_add(i), v); + } + } 0xFF56 => { self.infrared_com_port = val; }, - 0xFF70 => self.wram_bank = val, + 0xFF70 => { + println!("Set wram bank to {:02X}", val); + if val > 7 { + panic!("R u sure this is correct?"); + } + self.wram_bank = val; + } 0xFF80 ... 0xFFFE => { self.hiram[(addr - 0xFF80) as usize] = val; }, diff --git a/src/timer.rs b/src/timer.rs index 85d64e4..9854774 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -3,7 +3,8 @@ pub struct Timer { tima: u8, tma: u8, tac: u8, - timer_interrupt: bool + timer_interrupt: bool, + ctr: u16, } impl Timer { @@ -11,6 +12,14 @@ impl Timer { Timer::default() } + pub fn tick(&mut self, ticks: u16) { + self.ctr += ticks; + if self.ctr > 0x1000 { + self.ctr = 0; + self.timer_interrupt = true; + } + } + pub fn write_byte(&mut self, addr: u16, val: u8) { match addr { 0xFF05 => self.tima = val,