Add SET instruction; Add WRAM support
This commit is contained in:
parent
81567c97c4
commit
6d675616f1
91
src/cpu.rs
91
src/cpu.rs
@ -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"),
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
},
|
||||
|
||||
21
src/timer.rs
21
src/timer.rs
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user