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));
|
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);
|
panic!("Unsupported prefix instruction: {:x}", instruction);
|
||||||
}
|
}
|
||||||
@ -672,7 +746,10 @@ impl CPU {
|
|||||||
self.handle_interrupt(0x40, interconnect::INTERRUPT_DISPLAY_VBLANK);
|
self.handle_interrupt(0x40, interconnect::INTERRUPT_DISPLAY_VBLANK);
|
||||||
} else if e_pending & interconnect::INTERRUPT_DISPLAY_STAT > 0 {
|
} else if e_pending & interconnect::INTERRUPT_DISPLAY_STAT > 0 {
|
||||||
println!("Handling display stat interrupt");
|
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 {
|
} else if e_pending > 0 {
|
||||||
panic!("Unknown pending interrupt: {:02X}", e_pending);
|
panic!("Unknown pending interrupt: {:02X}", e_pending);
|
||||||
}
|
}
|
||||||
@ -905,7 +982,15 @@ impl CPU {
|
|||||||
|
|
||||||
8
|
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 => {
|
0x3B => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("DEC SP");
|
println!("DEC SP");
|
||||||
@ -1382,7 +1467,7 @@ impl CPU {
|
|||||||
if self.debug {
|
if self.debug {
|
||||||
println!("EI");
|
println!("EI");
|
||||||
}
|
}
|
||||||
//self.ime = true; // interrupt master enable
|
self.ime = true; // interrupt master enable
|
||||||
4
|
4
|
||||||
},
|
},
|
||||||
0xFC | 0xFD => panic!("NON-EXISTING OPCODE"),
|
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");
|
// panic!("Sprites not supported");
|
||||||
// Let's draw sprites.
|
// Let's draw sprites.
|
||||||
// TODO: Sprites with smaller X coordinate should
|
// 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;
|
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_STAT: u8 = 1 << 1;
|
||||||
pub const INTERRUPT_DISPLAY_VBLANK: u8 = 1 << 0;
|
pub const INTERRUPT_DISPLAY_VBLANK: u8 = 1 << 0;
|
||||||
|
|
||||||
@ -15,6 +17,7 @@ pub struct Interconnect {
|
|||||||
cartridge: cartridge::Cartridge,
|
cartridge: cartridge::Cartridge,
|
||||||
ram: Box<[u8]>,
|
ram: Box<[u8]>,
|
||||||
hiram: Box<[u8]>,
|
hiram: Box<[u8]>,
|
||||||
|
wram_bank: u8,
|
||||||
sound: sound::Sound,
|
sound: sound::Sound,
|
||||||
display: display::Display,
|
display: display::Display,
|
||||||
interrupt: u8,
|
interrupt: u8,
|
||||||
@ -24,6 +27,7 @@ pub struct Interconnect {
|
|||||||
serial: serial::Serial,
|
serial: serial::Serial,
|
||||||
timer: timer::Timer,
|
timer: timer::Timer,
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interconnect {
|
impl Interconnect {
|
||||||
@ -31,8 +35,9 @@ impl Interconnect {
|
|||||||
Interconnect {
|
Interconnect {
|
||||||
bios: bios,
|
bios: bios,
|
||||||
cartridge: cartridge::Cartridge::new(rom),
|
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(),
|
hiram: vec![0; HIRAM_SIZE].into_boxed_slice(),
|
||||||
|
wram_bank: 0,
|
||||||
sound: sound::Sound::new(),
|
sound: sound::Sound::new(),
|
||||||
display: display::Display::new(),
|
display: display::Display::new(),
|
||||||
// Refactor those
|
// Refactor those
|
||||||
@ -57,6 +62,10 @@ impl Interconnect {
|
|||||||
if self.display.stat_interrupt() {
|
if self.display.stat_interrupt() {
|
||||||
self.interrupt_request_flags |= INTERRUPT_DISPLAY_STAT;
|
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 {
|
pub fn is_boot_rom(&self) -> bool {
|
||||||
@ -78,9 +87,12 @@ impl Interconnect {
|
|||||||
0x100 ... 0x7FFF => self.cartridge.read_byte(addr),
|
0x100 ... 0x7FFF => self.cartridge.read_byte(addr),
|
||||||
0x8000 ... 0x9FFF => self.display.read_byte(addr),
|
0x8000 ... 0x9FFF => self.display.read_byte(addr),
|
||||||
0xA000 ... 0xBFFF => self.cartridge.read_byte(addr),
|
0xA000 ... 0xBFFF => self.cartridge.read_byte(addr),
|
||||||
0xC000 ... 0xDFFF => {
|
0xC000 ... 0xCFFF => {
|
||||||
self.ram[(addr - 0xC000) as usize]
|
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
|
0xFF00 => 0xFF, // TODO: This is the input stuff
|
||||||
0xFF01 ... 0xFF02 => self.serial.read_byte(addr),
|
0xFF01 ... 0xFF02 => self.serial.read_byte(addr),
|
||||||
0xFF04 ... 0xFF07 => self.timer.read_byte(addr),
|
0xFF04 ... 0xFF07 => self.timer.read_byte(addr),
|
||||||
@ -98,7 +110,8 @@ impl Interconnect {
|
|||||||
},
|
},
|
||||||
0xFF56 => {
|
0xFF56 => {
|
||||||
self.infrared_com_port
|
self.infrared_com_port
|
||||||
}
|
},
|
||||||
|
0xFF70 => self.wram_bank,
|
||||||
0xFF80 ... 0xFFFE => {
|
0xFF80 ... 0xFFFE => {
|
||||||
self.hiram[(addr - 0xFF80) as usize]
|
self.hiram[(addr - 0xFF80) as usize]
|
||||||
},
|
},
|
||||||
@ -130,9 +143,12 @@ impl Interconnect {
|
|||||||
0x0000 ... 0x7FFF => self.cartridge.write_byte(addr, val),
|
0x0000 ... 0x7FFF => self.cartridge.write_byte(addr, val),
|
||||||
0x8000 ... 0x9FFF => self.display.write_byte(addr, val),
|
0x8000 ... 0x9FFF => self.display.write_byte(addr, val),
|
||||||
0xA000 ... 0xBFFF => self.cartridge.write_byte(addr, val),
|
0xA000 ... 0xBFFF => self.cartridge.write_byte(addr, val),
|
||||||
0xC000 ... 0xDFFF => {
|
0xC000 ... 0xCFFF => {
|
||||||
self.ram[(addr - 0xC000) as usize] = val;
|
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
|
0xFE00 ... 0xFE9F => self.display.write_byte(addr, val), // OAM
|
||||||
0xFF01 ... 0xFF02 => self.serial.write_byte(addr, val),
|
0xFF01 ... 0xFF02 => self.serial.write_byte(addr, val),
|
||||||
0xFF04 ... 0xFF07 => self.timer.write_byte(addr, val),
|
0xFF04 ... 0xFF07 => self.timer.write_byte(addr, val),
|
||||||
@ -162,6 +178,7 @@ impl Interconnect {
|
|||||||
0xFF56 => {
|
0xFF56 => {
|
||||||
self.infrared_com_port = val;
|
self.infrared_com_port = val;
|
||||||
},
|
},
|
||||||
|
0xFF70 => self.wram_bank = val,
|
||||||
0xFF80 ... 0xFFFE => {
|
0xFF80 ... 0xFFFE => {
|
||||||
self.hiram[(addr - 0xFF80) as usize] = val;
|
self.hiram[(addr - 0xFF80) as usize] = val;
|
||||||
},
|
},
|
||||||
|
|||||||
21
src/timer.rs
21
src/timer.rs
@ -2,7 +2,8 @@
|
|||||||
pub struct Timer {
|
pub struct Timer {
|
||||||
tima: u8,
|
tima: u8,
|
||||||
tma: u8,
|
tma: u8,
|
||||||
tac: u8
|
tac: u8,
|
||||||
|
timer_interrupt: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Timer {
|
impl Timer {
|
||||||
@ -15,7 +16,7 @@ impl Timer {
|
|||||||
0xFF05 => self.tima = val,
|
0xFF05 => self.tima = val,
|
||||||
0xFF06 => self.tma = val,
|
0xFF06 => self.tma = val,
|
||||||
0xFF07 => self.tac = 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,
|
0xFF05 => self.tima,
|
||||||
0xFF06 => self.tma,
|
0xFF06 => self.tma,
|
||||||
0xFF07 => self.tac,
|
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