Add VRAM DMA; Add basic timer support
This commit is contained in:
parent
6d675616f1
commit
44c8b2e7d8
@ -1050,7 +1050,9 @@ impl CPU {
|
|||||||
// ADC
|
// ADC
|
||||||
0x88 ... 0x8F => {
|
0x88 ... 0x8F => {
|
||||||
let reg_id = (instruction - 0x88) as usize;
|
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 old = self.regs[REG_A];
|
||||||
let mut new = old.wrapping_add(self.get_8bit_reg(reg_id));
|
let mut new = old.wrapping_add(self.get_8bit_reg(reg_id));
|
||||||
|
|||||||
@ -27,7 +27,10 @@ pub struct Interconnect {
|
|||||||
serial: serial::Serial,
|
serial: serial::Serial,
|
||||||
timer: timer::Timer,
|
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 {
|
impl Interconnect {
|
||||||
@ -37,7 +40,7 @@ impl Interconnect {
|
|||||||
cartridge: cartridge::Cartridge::new(rom),
|
cartridge: cartridge::Cartridge::new(rom),
|
||||||
ram: vec![0; WRAM_SIZE].into_boxed_slice(),
|
ram: vec![0; WRAM_SIZE].into_boxed_slice(),
|
||||||
hiram: vec![0; HIRAM_SIZE].into_boxed_slice(),
|
hiram: vec![0; HIRAM_SIZE].into_boxed_slice(),
|
||||||
wram_bank: 0,
|
wram_bank: 1,
|
||||||
sound: sound::Sound::new(),
|
sound: sound::Sound::new(),
|
||||||
display: display::Display::new(),
|
display: display::Display::new(),
|
||||||
// Refactor those
|
// Refactor those
|
||||||
@ -48,12 +51,17 @@ impl Interconnect {
|
|||||||
timer: timer::Timer::new(),
|
timer: timer::Timer::new(),
|
||||||
serial: serial::Serial::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.
|
// Somehow we need different timers for this.
|
||||||
pub fn tick(&mut self, cycles: u8) {
|
pub fn tick(&mut self, cycles: u8) {
|
||||||
self.display.tick(cycles as u16 * 4);
|
self.display.tick(cycles as u16 * 4);
|
||||||
|
self.timer.tick(cycles as u16 * 4);
|
||||||
|
|
||||||
if self.display.vblank_interrupt() {
|
if self.display.vblank_interrupt() {
|
||||||
self.interrupt_request_flags |= INTERRUPT_DISPLAY_VBLANK;
|
self.interrupt_request_flags |= INTERRUPT_DISPLAY_VBLANK;
|
||||||
@ -108,6 +116,14 @@ impl Interconnect {
|
|||||||
0xFF50 => {
|
0xFF50 => {
|
||||||
self.disable_bootrom
|
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 => {
|
0xFF56 => {
|
||||||
self.infrared_com_port
|
self.infrared_com_port
|
||||||
},
|
},
|
||||||
@ -163,7 +179,7 @@ impl Interconnect {
|
|||||||
self.display.write_byte(addr, val);
|
self.display.write_byte(addr, val);
|
||||||
},
|
},
|
||||||
0xFF46 => {
|
0xFF46 => {
|
||||||
println!("DMA transfer: ");
|
println!("OAM DMA transfer: ");
|
||||||
for x in 0x00 .. 0x9F {
|
for x in 0x00 .. 0x9F {
|
||||||
let dma_b = self.read_byte(((val as u16) << 8) | x);
|
let dma_b = self.read_byte(((val as u16) << 8) | x);
|
||||||
self.write_byte(0xFE00 | x, dma_b);
|
self.write_byte(0xFE00 | x, dma_b);
|
||||||
@ -175,10 +191,30 @@ impl Interconnect {
|
|||||||
println!("Disabling boot rom.");
|
println!("Disabling boot rom.");
|
||||||
self.disable_bootrom = val;
|
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 => {
|
0xFF56 => {
|
||||||
self.infrared_com_port = val;
|
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 => {
|
0xFF80 ... 0xFFFE => {
|
||||||
self.hiram[(addr - 0xFF80) as usize] = val;
|
self.hiram[(addr - 0xFF80) as usize] = val;
|
||||||
},
|
},
|
||||||
|
|||||||
11
src/timer.rs
11
src/timer.rs
@ -3,7 +3,8 @@ pub struct Timer {
|
|||||||
tima: u8,
|
tima: u8,
|
||||||
tma: u8,
|
tma: u8,
|
||||||
tac: u8,
|
tac: u8,
|
||||||
timer_interrupt: bool
|
timer_interrupt: bool,
|
||||||
|
ctr: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Timer {
|
impl Timer {
|
||||||
@ -11,6 +12,14 @@ impl Timer {
|
|||||||
Timer::default()
|
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) {
|
pub fn write_byte(&mut self, addr: u16, val: u8) {
|
||||||
match addr {
|
match addr {
|
||||||
0xFF05 => self.tima = val,
|
0xFF05 => self.tima = val,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user