Add SET instruction; Add WRAM support

This commit is contained in:
Kevin Hamacher 2016-05-28 23:34:32 +02:00
parent 81567c97c4
commit 6d675616f1
4 changed files with 129 additions and 12 deletions

View File

@ -384,6 +384,80 @@ impl CPU {
}
self.set_8bit_reg(reg_id, reg_content & !(1 << 7));
}
// Set bits
0xC0 ... 0xC7 => {
// Set 0th bit
let reg_id = (instruction - 0xC0) as usize;
let reg_content = self.get_8bit_reg(reg_id);
if self.debug {
println!("SET 0, {}", REG_NAMES[reg_id]);
}
self.set_8bit_reg(reg_id, reg_content | (1 << 0));
}
0xC8 ... 0xCF => {
// Set 1th bit
let reg_id = (instruction - 0xC8) as usize;
let reg_content = self.get_8bit_reg(reg_id);
if self.debug {
println!("SET 1, {}", REG_NAMES[reg_id]);
}
self.set_8bit_reg(reg_id, reg_content | (1 << 1));
}
0xD0 ... 0xD7 => {
// Set 2nd bit
let reg_id = (instruction - 0xD0) as usize;
let reg_content = self.get_8bit_reg(reg_id);
if self.debug {
println!("SET 2, {}", REG_NAMES[reg_id]);
}
self.set_8bit_reg(reg_id, reg_content | (1 << 2));
}
0xD8 ... 0xDF => {
// Set 3th bit
let reg_id = (instruction - 0xD8) as usize;
let reg_content = self.get_8bit_reg(reg_id);
if self.debug {
println!("SET 3, {}", REG_NAMES[reg_id]);
}
self.set_8bit_reg(reg_id, reg_content | (1 << 3));
}
0xE0 ... 0xE7 => {
// Set 4th bit
let reg_id = (instruction - 0xE0) as usize;
let reg_content = self.get_8bit_reg(reg_id);
if self.debug {
println!("SET 4, {}", REG_NAMES[reg_id]);
}
self.set_8bit_reg(reg_id, reg_content | (1 << 4));
}
0xE8 ... 0xEF => {
// Set 5th bit
let reg_id = (instruction - 0xE8) as usize;
let reg_content = self.get_8bit_reg(reg_id);
if self.debug {
println!("SET 5, {}", REG_NAMES[reg_id]);
}
self.set_8bit_reg(reg_id, reg_content | (1 << 5));
}
0xF0 ... 0xF7 => {
// Set 6th bit
let reg_id = (instruction - 0xF0) as usize;
let reg_content = self.get_8bit_reg(reg_id);
if self.debug {
println!("SET 6, {}", REG_NAMES[reg_id]);
}
self.set_8bit_reg(reg_id, reg_content | (1 << 6));
}
0xF8 ... 0xFF => {
// Set 7th bit
let reg_id = (instruction - 0xF8) as usize;
let reg_content = self.get_8bit_reg(reg_id);
if self.debug {
println!("SET 7, {}", REG_NAMES[reg_id]);
}
self.set_8bit_reg(reg_id, reg_content | (1 << 7));
}
_ => {
panic!("Unsupported prefix instruction: {:x}", instruction);
}
@ -672,7 +746,10 @@ impl CPU {
self.handle_interrupt(0x40, interconnect::INTERRUPT_DISPLAY_VBLANK);
} else if e_pending & interconnect::INTERRUPT_DISPLAY_STAT > 0 {
println!("Handling display stat interrupt");
self.handle_interrupt(0x40, interconnect::INTERRUPT_DISPLAY_STAT);
self.handle_interrupt(0x48, interconnect::INTERRUPT_DISPLAY_STAT);
} else if e_pending & interconnect::INTERRUPT_TIMER_OVERFLOW > 0{
println!("Handling timer interrupt");
self.handle_interrupt(0x50, interconnect::INTERRUPT_TIMER_OVERFLOW);
} else if e_pending > 0 {
panic!("Unknown pending interrupt: {:02X}", e_pending);
}
@ -905,7 +982,15 @@ impl CPU {
8
},
0x3A => panic!("LD A, (HL-) not implemented"),
0x3A => {
if self.debug {
println!("LD A, (HL-)");
}
let mut addr = self.get_pair_value(REG_N_H, REG_N_L);
self.regs[REG_A] = self.interconnect.read_byte(addr);
self.set_pair_value(REG_N_H, REG_N_L, addr.wrapping_sub(1));
8
}
0x3B => {
if self.debug {
println!("DEC SP");
@ -1382,7 +1467,7 @@ impl CPU {
if self.debug {
println!("EI");
}
//self.ime = true; // interrupt master enable
self.ime = true; // interrupt master enable
4
},
0xFC | 0xFD => panic!("NON-EXISTING OPCODE"),

View File

@ -340,7 +340,7 @@ impl Display {
}
if self.control & CTRL_BG_SPRITE_ENABLE > 0 {
if self.control & CTRL_BG_SPRITE_ENABLE > 0 && false {
// panic!("Sprites not supported");
// Let's draw sprites.
// TODO: Sprites with smaller X coordinate should

View File

@ -1,6 +1,8 @@
const RAM_SIZE: usize = 0x2000;
// const RAM_SIZE: usize = 0x2000;
const WRAM_SIZE: usize = 0x8000;
const HIRAM_SIZE: usize = (0xFFFE - 0xFF80) + 1;
pub const INTERRUPT_TIMER_OVERFLOW: u8 = 1 << 2;
pub const INTERRUPT_DISPLAY_STAT: u8 = 1 << 1;
pub const INTERRUPT_DISPLAY_VBLANK: u8 = 1 << 0;
@ -15,6 +17,7 @@ pub struct Interconnect {
cartridge: cartridge::Cartridge,
ram: Box<[u8]>,
hiram: Box<[u8]>,
wram_bank: u8,
sound: sound::Sound,
display: display::Display,
interrupt: u8,
@ -24,6 +27,7 @@ pub struct Interconnect {
serial: serial::Serial,
timer: timer::Timer,
}
impl Interconnect {
@ -31,8 +35,9 @@ impl Interconnect {
Interconnect {
bios: bios,
cartridge: cartridge::Cartridge::new(rom),
ram: vec![0; RAM_SIZE].into_boxed_slice(),
ram: vec![0; WRAM_SIZE].into_boxed_slice(),
hiram: vec![0; HIRAM_SIZE].into_boxed_slice(),
wram_bank: 0,
sound: sound::Sound::new(),
display: display::Display::new(),
// Refactor those
@ -57,6 +62,10 @@ impl Interconnect {
if self.display.stat_interrupt() {
self.interrupt_request_flags |= INTERRUPT_DISPLAY_STAT;
}
if self.timer.timer_interrupt() {
self.interrupt_request_flags |= INTERRUPT_TIMER_OVERFLOW;
}
}
pub fn is_boot_rom(&self) -> bool {
@ -78,9 +87,12 @@ impl Interconnect {
0x100 ... 0x7FFF => self.cartridge.read_byte(addr),
0x8000 ... 0x9FFF => self.display.read_byte(addr),
0xA000 ... 0xBFFF => self.cartridge.read_byte(addr),
0xC000 ... 0xDFFF => {
0xC000 ... 0xCFFF => {
self.ram[(addr - 0xC000) as usize]
},
0xD000 ... 0xDFFF => {
self.ram[(addr - 0xD000) as usize + self.wram_bank as usize * 0x1000]
}
0xFF00 => 0xFF, // TODO: This is the input stuff
0xFF01 ... 0xFF02 => self.serial.read_byte(addr),
0xFF04 ... 0xFF07 => self.timer.read_byte(addr),
@ -98,7 +110,8 @@ impl Interconnect {
},
0xFF56 => {
self.infrared_com_port
}
},
0xFF70 => self.wram_bank,
0xFF80 ... 0xFFFE => {
self.hiram[(addr - 0xFF80) as usize]
},
@ -130,9 +143,12 @@ impl Interconnect {
0x0000 ... 0x7FFF => self.cartridge.write_byte(addr, val),
0x8000 ... 0x9FFF => self.display.write_byte(addr, val),
0xA000 ... 0xBFFF => self.cartridge.write_byte(addr, val),
0xC000 ... 0xDFFF => {
0xC000 ... 0xCFFF => {
self.ram[(addr - 0xC000) as usize] = val;
},
0xD000 ... 0xDFFF => {
self.ram[(addr - 0xD000) as usize + self.wram_bank as usize * 0x1000] = val;
}
0xFE00 ... 0xFE9F => self.display.write_byte(addr, val), // OAM
0xFF01 ... 0xFF02 => self.serial.write_byte(addr, val),
0xFF04 ... 0xFF07 => self.timer.write_byte(addr, val),
@ -162,6 +178,7 @@ impl Interconnect {
0xFF56 => {
self.infrared_com_port = val;
},
0xFF70 => self.wram_bank = val,
0xFF80 ... 0xFFFE => {
self.hiram[(addr - 0xFF80) as usize] = val;
},

View File

@ -2,7 +2,8 @@
pub struct Timer {
tima: u8,
tma: u8,
tac: u8
tac: u8,
timer_interrupt: bool
}
impl Timer {
@ -15,7 +16,7 @@ impl Timer {
0xFF05 => self.tima = val,
0xFF06 => self.tma = val,
0xFF07 => self.tac = val,
_ => panic!("Timer: Write {:02X} to {:04X} unsupported", val, addr),
_ => println!("Timer: Write {:02X} to {:04X} unsupported", val, addr),
}
}
@ -24,7 +25,21 @@ impl Timer {
0xFF05 => self.tima,
0xFF06 => self.tma,
0xFF07 => self.tac,
_ => panic!("Timer: Read from {:04X} unsupported", addr),
_ => {
println!("Timer: Read from {:04X} unsupported", addr);
0
},
}
}
pub fn timer_interrupt(&mut self) -> bool {
// Returns whether or not a vblank interrupt should be done
// Yes, this is polling, and yes, this sucks.\
if self.timer_interrupt {
self.timer_interrupt = false;
true
} else {
false
}
}
}