Even more cleanup
This commit is contained in:
parent
79d2c99c06
commit
0fdfa9ae63
362
src/cpu.rs
362
src/cpu.rs
@ -8,6 +8,14 @@ const REG_H: usize = 4;
|
|||||||
const REG_L: usize = 5;
|
const REG_L: usize = 5;
|
||||||
const REG_A: usize = 6;
|
const REG_A: usize = 6;
|
||||||
|
|
||||||
|
const REG_N_B: usize = 0;
|
||||||
|
const REG_N_C: usize = 1;
|
||||||
|
const REG_N_D: usize = 2;
|
||||||
|
const REG_N_E: usize = 3;
|
||||||
|
const REG_N_H: usize = 4;
|
||||||
|
const REG_N_L: usize = 5;
|
||||||
|
const REG_N_HL: usize = 6;
|
||||||
|
const REG_N_A: usize = 7;
|
||||||
const REG_NAMES: [&'static str; 8] = ["B", "C", "D", "E", "H", "L", "(HL)", "A"];
|
const REG_NAMES: [&'static str; 8] = ["B", "C", "D", "E", "H", "L", "(HL)", "A"];
|
||||||
|
|
||||||
const FLAG_Z: u8 = 1 << 7;
|
const FLAG_Z: u8 = 1 << 7;
|
||||||
@ -35,8 +43,6 @@ fn to_u16(bytes: Box<[u8]>) -> u16 {
|
|||||||
|
|
||||||
impl CPU {
|
impl CPU {
|
||||||
pub fn new(interconnect: interconnect::Interconnect) -> CPU {
|
pub fn new(interconnect: interconnect::Interconnect) -> CPU {
|
||||||
// Ugly patch ^.^
|
|
||||||
// interconnect.write_byte(0xFF44 as u16, 0x90);
|
|
||||||
CPU {
|
CPU {
|
||||||
flags: 0,
|
flags: 0,
|
||||||
regs: [0, 0, 0, 0, 0, 0, 0],
|
regs: [0, 0, 0, 0, 0, 0, 0],
|
||||||
@ -223,15 +229,49 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reg_inc(&mut self, reg_id: usize) {
|
fn push_rr(&mut self, r1: usize, r2: usize) -> u8 {
|
||||||
|
if self.debug {
|
||||||
|
println!("PUSH {}{}", REG_NAMES[r1], REG_NAMES[r2]);
|
||||||
|
}
|
||||||
|
let val: u16 = self.get_pair_value(r1, r2);
|
||||||
|
self.push(val);
|
||||||
|
16
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&mut self, val: u16) {
|
||||||
|
self.interconnect.write_word(self.sp - 2, val);
|
||||||
|
self.sp -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ld_r_r(&mut self, reg_dst: usize, reg_src: usize) -> u8 {
|
||||||
|
if self.debug {
|
||||||
|
println!("LD {}, {}", REG_NAMES[reg_dst], REG_NAMES[reg_src])
|
||||||
|
}
|
||||||
|
let sv = self.get_8bit_reg(reg_src);
|
||||||
|
self.set_8bit_reg(reg_dst, sv);
|
||||||
|
if reg_dst == REG_N_HL || reg_src == REG_N_HL {
|
||||||
|
8
|
||||||
|
} else {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reg_inc(&mut self, reg_id: usize) -> u8 {
|
||||||
|
if self.debug {
|
||||||
|
println!("INC {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[reg_id] = self.regs[reg_id].wrapping_add(1);
|
self.regs[reg_id] = self.regs[reg_id].wrapping_add(1);
|
||||||
if self.regs[reg_id] == 0 {
|
if self.regs[reg_id] == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.flags |= FLAG_Z;
|
||||||
}
|
}
|
||||||
self.flags &= !FLAG_N;
|
self.flags &= !FLAG_N;
|
||||||
|
4
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reg_dec(&mut self, reg_id: usize) {
|
fn reg_dec(&mut self, reg_id: usize) -> u8 {
|
||||||
|
if self.debug {
|
||||||
|
println!("DEC {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[reg_id] = self.regs[reg_id].wrapping_sub(1);
|
self.regs[reg_id] = self.regs[reg_id].wrapping_sub(1);
|
||||||
if self.regs[reg_id] == 0 {
|
if self.regs[reg_id] == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.flags |= FLAG_Z;
|
||||||
@ -239,6 +279,7 @@ impl CPU {
|
|||||||
self.flags &= !FLAG_Z;
|
self.flags &= !FLAG_Z;
|
||||||
}
|
}
|
||||||
self.flags |= FLAG_N;
|
self.flags |= FLAG_N;
|
||||||
|
4
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_flag(&mut self, flag: u8) {
|
fn set_flag(&mut self, flag: u8) {
|
||||||
@ -268,14 +309,12 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
|
|
||||||
let cycles: u16;
|
let cycles: u8 = match instruction {
|
||||||
|
|
||||||
match instruction {
|
|
||||||
0x00 => {
|
0x00 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("NOP");
|
println!("NOP");
|
||||||
}
|
}
|
||||||
cycles = 4;
|
4
|
||||||
},
|
},
|
||||||
0x01 => {
|
0x01 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
@ -284,7 +323,7 @@ impl CPU {
|
|||||||
let addr: u16 = self.get_pair_value(REG_B, REG_C);
|
let addr: u16 = self.get_pair_value(REG_B, REG_C);
|
||||||
let val: u8 = self.regs[REG_A];
|
let val: u8 = self.regs[REG_A];
|
||||||
self.interconnect.write_byte(addr, val);
|
self.interconnect.write_byte(addr, val);
|
||||||
cycles = 12;
|
12
|
||||||
},
|
},
|
||||||
0x02 => {
|
0x02 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
@ -293,51 +332,27 @@ impl CPU {
|
|||||||
let addr: u16 = self.get_pair_value(REG_B, REG_C);
|
let addr: u16 = self.get_pair_value(REG_B, REG_C);
|
||||||
let val: u8 = self.regs[REG_A];
|
let val: u8 = self.regs[REG_A];
|
||||||
self.interconnect.write_byte(addr, val);
|
self.interconnect.write_byte(addr, val);
|
||||||
cycles = 8;
|
8
|
||||||
},
|
|
||||||
0x04 => {
|
|
||||||
if self.debug{
|
|
||||||
println!("INC B");
|
|
||||||
}
|
|
||||||
self.reg_inc(REG_B);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x05 => {
|
|
||||||
if self.debug {
|
|
||||||
println!("DEC B");
|
|
||||||
}
|
|
||||||
self.reg_dec(REG_B);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
},
|
||||||
|
0x04 => self.reg_inc(REG_B),
|
||||||
|
0x05 => self.reg_dec(REG_B),
|
||||||
0x06 => {
|
0x06 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("LD B, {:02x}", args[0]);
|
println!("LD B, {:02x}", args[0]);
|
||||||
}
|
}
|
||||||
self.regs[REG_B] = args[0];
|
self.regs[REG_B] = args[0];
|
||||||
cycles = 8;
|
8
|
||||||
},
|
|
||||||
0x0C => {
|
|
||||||
if self.debug {
|
|
||||||
println!("INC C");
|
|
||||||
}
|
|
||||||
self.reg_inc(REG_C);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x0D => {
|
|
||||||
if self.debug {
|
|
||||||
println!("DEC C");
|
|
||||||
}
|
|
||||||
self.reg_dec(REG_C);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
},
|
||||||
|
0x0C => self.reg_inc(REG_C),
|
||||||
|
0x0D => self.reg_dec(REG_C),
|
||||||
0x0E => {
|
0x0E => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("LD C, {:02x}", args[0]);
|
println!("LD C, {:02x}", args[0]);
|
||||||
}
|
}
|
||||||
self.regs[REG_C] = args[0];
|
self.regs[REG_C] = args[0];
|
||||||
cycles = 8;
|
8
|
||||||
},
|
},
|
||||||
0x11 => {
|
0x11 => {
|
||||||
let args = self.load_args(2);
|
let args = self.load_args(2);
|
||||||
@ -346,7 +361,7 @@ impl CPU {
|
|||||||
println!("LD DE, {:04x}", val);
|
println!("LD DE, {:04x}", val);
|
||||||
}
|
}
|
||||||
self.set_pair_value(REG_D, REG_E, val);
|
self.set_pair_value(REG_D, REG_E, val);
|
||||||
cycles = 12;
|
12
|
||||||
},
|
},
|
||||||
0x12 => {
|
0x12 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
@ -355,7 +370,7 @@ impl CPU {
|
|||||||
let addr: u16 = self.get_pair_value(REG_D, REG_E);
|
let addr: u16 = self.get_pair_value(REG_D, REG_E);
|
||||||
let val: u8 = self.regs[REG_A];
|
let val: u8 = self.regs[REG_A];
|
||||||
self.interconnect.write_byte(addr, val);
|
self.interconnect.write_byte(addr, val);
|
||||||
cycles = 12;
|
12
|
||||||
},
|
},
|
||||||
0x13 => {
|
0x13 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
@ -363,29 +378,17 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
let old_value = self.get_pair_value(REG_D, REG_E);
|
let old_value = self.get_pair_value(REG_D, REG_E);
|
||||||
self.set_pair_value(REG_D, REG_E, old_value + 1);
|
self.set_pair_value(REG_D, REG_E, old_value + 1);
|
||||||
cycles = 8;
|
8
|
||||||
},
|
|
||||||
0x14 => {
|
|
||||||
if self.debug {
|
|
||||||
println!("INC D");
|
|
||||||
}
|
|
||||||
self.reg_inc(REG_D);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x15 => {
|
|
||||||
if self.debug {
|
|
||||||
println!("DEC D");
|
|
||||||
}
|
|
||||||
self.reg_dec(REG_D);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
},
|
||||||
|
0x14 => self.reg_inc(REG_D),
|
||||||
|
0x15 => self.reg_dec(REG_D),
|
||||||
0x16 => {
|
0x16 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("LD D, {:02x}", args[0]);
|
println!("LD D, {:02x}", args[0]);
|
||||||
}
|
}
|
||||||
self.regs[REG_D] = args[0];
|
self.regs[REG_D] = args[0];
|
||||||
cycles = 8;
|
8
|
||||||
},
|
},
|
||||||
0x17 => {
|
0x17 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
@ -404,7 +407,7 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
self.regs[REG_A] = self.regs[REG_A] << 1 | 1;
|
self.regs[REG_A] = self.regs[REG_A] << 1 | 1;
|
||||||
}
|
}
|
||||||
cycles = 4;
|
4
|
||||||
},
|
},
|
||||||
0x18 => {
|
0x18 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
@ -417,36 +420,24 @@ impl CPU {
|
|||||||
} else {
|
} else {
|
||||||
self.ip += off as u16;
|
self.ip += off as u16;
|
||||||
}
|
}
|
||||||
cycles = 12;
|
12
|
||||||
},
|
},
|
||||||
0x1A => {
|
0x1A => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("LD A, (DE)");
|
println!("LD A, (DE)");
|
||||||
}
|
}
|
||||||
self.regs[REG_A] = self.interconnect.read_byte(self.get_pair_value(REG_D, REG_E));
|
self.regs[REG_A] = self.interconnect.read_byte(self.get_pair_value(REG_D, REG_E));
|
||||||
cycles = 8;
|
8
|
||||||
},
|
|
||||||
0x1C => {
|
|
||||||
if self.debug {
|
|
||||||
println!("INC E");
|
|
||||||
}
|
|
||||||
self.reg_inc(REG_E);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x1D => {
|
|
||||||
if self.debug {
|
|
||||||
println!("DEC E");
|
|
||||||
}
|
|
||||||
self.reg_dec(REG_E);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
},
|
||||||
|
0x1C => self.reg_inc(REG_E),
|
||||||
|
0x1D => self.reg_dec(REG_E),
|
||||||
0x1E => {
|
0x1E => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("LD E, {:02x}", args[0]);
|
println!("LD E, {:02x}", args[0]);
|
||||||
}
|
}
|
||||||
self.regs[REG_E] = args[0];
|
self.regs[REG_E] = args[0];
|
||||||
cycles = 8;
|
8
|
||||||
},
|
},
|
||||||
0x20 => {
|
0x20 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
@ -460,9 +451,9 @@ impl CPU {
|
|||||||
} else {
|
} else {
|
||||||
self.ip += offset as u16;
|
self.ip += offset as u16;
|
||||||
}
|
}
|
||||||
cycles = 12;
|
12
|
||||||
} else {
|
} else {
|
||||||
cycles = 8;
|
8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0x21 => {
|
0x21 => {
|
||||||
@ -471,7 +462,7 @@ impl CPU {
|
|||||||
println!("LD HL, {:04x}", value);
|
println!("LD HL, {:04x}", value);
|
||||||
}
|
}
|
||||||
self.set_pair_value(REG_H, REG_L, value);
|
self.set_pair_value(REG_H, REG_L, value);
|
||||||
cycles = 12;
|
12
|
||||||
},
|
},
|
||||||
0x22 => {
|
0x22 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
@ -480,7 +471,7 @@ impl CPU {
|
|||||||
let addr: u16 = self.get_pair_value(REG_H, REG_L);
|
let addr: u16 = self.get_pair_value(REG_H, REG_L);
|
||||||
self.interconnect.write_byte(addr, self.regs[REG_A]);
|
self.interconnect.write_byte(addr, self.regs[REG_A]);
|
||||||
self.set_pair_value(REG_H, REG_L, addr + 1);
|
self.set_pair_value(REG_H, REG_L, addr + 1);
|
||||||
cycles = 8;
|
8
|
||||||
},
|
},
|
||||||
0x23 => {
|
0x23 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
@ -488,29 +479,17 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
let old_value = self.get_pair_value(REG_H, REG_L);
|
let old_value = self.get_pair_value(REG_H, REG_L);
|
||||||
self.set_pair_value(REG_H, REG_L, old_value + 1);
|
self.set_pair_value(REG_H, REG_L, old_value + 1);
|
||||||
cycles = 8;
|
8
|
||||||
},
|
|
||||||
0x24 => {
|
|
||||||
if self.debug {
|
|
||||||
println!("INC H");
|
|
||||||
}
|
|
||||||
self.reg_inc(REG_H);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x25 => {
|
|
||||||
if self.debug {
|
|
||||||
println!("DEC H");
|
|
||||||
}
|
|
||||||
self.reg_dec(REG_H);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
},
|
||||||
|
0x24 => self.reg_inc(REG_H),
|
||||||
|
0x25 => self.reg_dec(REG_H),
|
||||||
0x26 => {
|
0x26 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("LD H, {:02x}", args[0]);
|
println!("LD H, {:02x}", args[0]);
|
||||||
}
|
}
|
||||||
self.regs[REG_H] = args[0];
|
self.regs[REG_H] = args[0];
|
||||||
cycles = 8;
|
8
|
||||||
},
|
},
|
||||||
0x28 => {
|
0x28 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
@ -525,9 +504,9 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
if self.flags & FLAG_Z > 0 {
|
if self.flags & FLAG_Z > 0 {
|
||||||
self.ip = target;
|
self.ip = target;
|
||||||
cycles = 12;
|
12
|
||||||
} else {
|
} else {
|
||||||
cycles = 8;
|
8
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0x2A => {
|
0x2A => {
|
||||||
@ -536,29 +515,17 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
let addr: u16 = self.get_pair_value(REG_H, REG_L);
|
let addr: u16 = self.get_pair_value(REG_H, REG_L);
|
||||||
self.regs[REG_A] = self.interconnect.read_byte(addr);
|
self.regs[REG_A] = self.interconnect.read_byte(addr);
|
||||||
cycles = 8;
|
8
|
||||||
},
|
|
||||||
0x2C => {
|
|
||||||
if self.debug {
|
|
||||||
println!("INC L");
|
|
||||||
}
|
|
||||||
self.reg_inc(REG_L);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x2D => {
|
|
||||||
if self.debug {
|
|
||||||
println!("DEC L");
|
|
||||||
}
|
|
||||||
self.reg_dec(REG_L);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
},
|
||||||
|
0x2C => self.reg_inc(REG_L),
|
||||||
|
0x2D => self.reg_dec(REG_L),
|
||||||
0x2E => {
|
0x2E => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("LD L, {:02x}", args[0]);
|
println!("LD L, {:02x}", args[0]);
|
||||||
}
|
}
|
||||||
self.regs[REG_L] = args[0];
|
self.regs[REG_L] = args[0];
|
||||||
cycles = 8;
|
8
|
||||||
},
|
},
|
||||||
0x31 => {
|
0x31 => {
|
||||||
let args = self.load_args(2);
|
let args = self.load_args(2);
|
||||||
@ -566,7 +533,7 @@ impl CPU {
|
|||||||
if self.debug {
|
if self.debug {
|
||||||
println!("LD SP, {:02x}", self.sp);
|
println!("LD SP, {:02x}", self.sp);
|
||||||
}
|
}
|
||||||
cycles = 12;
|
12
|
||||||
},
|
},
|
||||||
0x32 => {
|
0x32 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
@ -577,7 +544,7 @@ impl CPU {
|
|||||||
|
|
||||||
addr -= 1;
|
addr -= 1;
|
||||||
self.set_pair_value(REG_H, REG_L, addr);
|
self.set_pair_value(REG_H, REG_L, addr);
|
||||||
cycles = 8;
|
8
|
||||||
},
|
},
|
||||||
0x36 => {
|
0x36 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
@ -586,99 +553,28 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
let addr = self.get_pair_value(REG_H, REG_L);
|
let addr = self.get_pair_value(REG_H, REG_L);
|
||||||
self.interconnect.write_byte(addr, args[0]);
|
self.interconnect.write_byte(addr, args[0]);
|
||||||
cycles = 12;
|
12
|
||||||
},
|
},
|
||||||
0x3C => {
|
0x3C => self.reg_inc(REG_A),
|
||||||
if self.debug {
|
0x3D => self.reg_dec(REG_A),
|
||||||
println!("INC A");
|
|
||||||
}
|
|
||||||
self.reg_inc(REG_A);
|
|
||||||
cycles = 4;
|
|
||||||
}
|
|
||||||
0x3D => {
|
|
||||||
if self.debug {
|
|
||||||
println!("DEC A");
|
|
||||||
}
|
|
||||||
self.reg_dec(REG_A);
|
|
||||||
cycles = 4;
|
|
||||||
}
|
|
||||||
0x3E => {
|
0x3E => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("LD A, {:02x}", args[0]);
|
println!("LD A, {:02x}", args[0]);
|
||||||
}
|
}
|
||||||
self.regs[REG_A] = args[0];
|
self.regs[REG_A] = args[0];
|
||||||
cycles = 8;
|
8
|
||||||
},
|
},
|
||||||
|
|
||||||
// LDs
|
// LDs
|
||||||
0x40 ... 0x47 => {
|
0x40 ... 0x47 => self.ld_r_r(REG_N_B, (instruction - 0x40) as usize),
|
||||||
let reg_id = (instruction - 0x40) as usize;
|
0x48 ... 0x4F => self.ld_r_r(REG_N_C, (instruction - 0x48) as usize),
|
||||||
if self.debug {
|
0x50 ... 0x57 => self.ld_r_r(REG_N_D, (instruction - 0x50) as usize),
|
||||||
println!("LD B, {}", REG_NAMES[reg_id]);
|
0x58 ... 0x5F => self.ld_r_r(REG_N_E, (instruction - 0x58) as usize),
|
||||||
}
|
0x60 ... 0x67 => self.ld_r_r(REG_N_H, (instruction - 0x60) as usize),
|
||||||
self.regs[REG_B] = self.get_8bit_reg(reg_id);
|
0x68 ... 0x6F => self.ld_r_r(REG_N_L, (instruction - 0x68) as usize),
|
||||||
cycles = 4;
|
0x70 ... 0x75 | 0x77 => self.ld_r_r(REG_N_HL, (instruction - 0x70) as usize),
|
||||||
},
|
0x78 ... 0x7F => self.ld_r_r(REG_N_A, (instruction - 0x78) as usize),
|
||||||
0x48 ... 0x4F => {
|
|
||||||
let reg_id = (instruction - 0x48) as usize;
|
|
||||||
if self.debug {
|
|
||||||
println!("LD C, {}", REG_NAMES[reg_id]);
|
|
||||||
}
|
|
||||||
self.regs[REG_C] = self.get_8bit_reg(reg_id);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x50 ... 0x57 => {
|
|
||||||
let reg_id = (instruction - 0x50) as usize;
|
|
||||||
if self.debug {
|
|
||||||
println!("LD D, {}", REG_NAMES[reg_id]);
|
|
||||||
}
|
|
||||||
self.regs[REG_D] = self.get_8bit_reg(reg_id);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x58 ... 0x5F => {
|
|
||||||
let reg_id = (instruction - 0x58) as usize;
|
|
||||||
if self.debug {
|
|
||||||
println!("LD E, {}", REG_NAMES[reg_id]);
|
|
||||||
}
|
|
||||||
self.regs[REG_E] = self.get_8bit_reg(reg_id);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x60 ... 0x67 => {
|
|
||||||
let reg_id = (instruction - 0x60) as usize;
|
|
||||||
if self.debug {
|
|
||||||
println!("LD H, {}", REG_NAMES[reg_id]);
|
|
||||||
}
|
|
||||||
self.regs[REG_H] = self.get_8bit_reg(reg_id);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x68 ... 0x6F => {
|
|
||||||
let reg_id = (instruction - 0x68) as usize;
|
|
||||||
if self.debug {
|
|
||||||
println!("LD L, {}", REG_NAMES[reg_id]);
|
|
||||||
}
|
|
||||||
self.regs[REG_L] = self.get_8bit_reg(reg_id);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
0x70 ... 0x75 | 0x77 => {
|
|
||||||
let reg_id = (instruction - 0x70) as usize;
|
|
||||||
if self.debug {
|
|
||||||
println!("LD (HL), {}", REG_NAMES[reg_id]);
|
|
||||||
}
|
|
||||||
let reg_value: u8 = self.get_8bit_reg(reg_id);
|
|
||||||
let addr: u16 = self.get_pair_value(REG_H, REG_L);
|
|
||||||
cycles = 8;
|
|
||||||
|
|
||||||
self.interconnect.write_byte(addr, reg_value);
|
|
||||||
},
|
|
||||||
0x78 ... 0x7F => {
|
|
||||||
let reg_id = (instruction - 0x78) as usize;
|
|
||||||
if self.debug {
|
|
||||||
println!("LD A, {}", REG_NAMES[reg_id]);
|
|
||||||
}
|
|
||||||
self.regs[REG_A] = self.get_8bit_reg(reg_id);
|
|
||||||
cycles = 4;
|
|
||||||
},
|
|
||||||
|
|
||||||
// ADD
|
// ADD
|
||||||
0x80 ... 0x87 => {
|
0x80 ... 0x87 => {
|
||||||
@ -689,7 +585,7 @@ impl CPU {
|
|||||||
self.regs[REG_A] = self.regs[REG_A].wrapping_add(self.get_8bit_reg(reg_id));
|
self.regs[REG_A] = self.regs[REG_A].wrapping_add(self.get_8bit_reg(reg_id));
|
||||||
|
|
||||||
self.clear_flag(FLAG_N);
|
self.clear_flag(FLAG_N);
|
||||||
cycles = 4;
|
4
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADC
|
// ADC
|
||||||
@ -702,7 +598,7 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.set_flag(FLAG_N);
|
self.set_flag(FLAG_N);
|
||||||
cycles = 4;
|
4
|
||||||
}
|
}
|
||||||
|
|
||||||
// SUBs
|
// SUBs
|
||||||
@ -719,7 +615,7 @@ impl CPU {
|
|||||||
self.clear_flag(FLAG_Z);
|
self.clear_flag(FLAG_Z);
|
||||||
}
|
}
|
||||||
// TODO: H, C
|
// TODO: H, C
|
||||||
cycles = 4;
|
4
|
||||||
}
|
}
|
||||||
|
|
||||||
// SBC
|
// SBC
|
||||||
@ -738,7 +634,7 @@ impl CPU {
|
|||||||
} else {
|
} else {
|
||||||
self.clear_flag(FLAG_Z);
|
self.clear_flag(FLAG_Z);
|
||||||
}
|
}
|
||||||
cycles = 4;
|
4
|
||||||
}
|
}
|
||||||
|
|
||||||
// XOR
|
// XOR
|
||||||
@ -757,7 +653,7 @@ impl CPU {
|
|||||||
self.clear_flag(FLAG_C);
|
self.clear_flag(FLAG_C);
|
||||||
self.clear_flag(FLAG_N);
|
self.clear_flag(FLAG_N);
|
||||||
self.clear_flag(FLAG_H);
|
self.clear_flag(FLAG_H);
|
||||||
cycles = 4;
|
4
|
||||||
},
|
},
|
||||||
|
|
||||||
// CP
|
// CP
|
||||||
@ -779,7 +675,7 @@ impl CPU {
|
|||||||
self.clear_flag(FLAG_C);
|
self.clear_flag(FLAG_C);
|
||||||
self.clear_flag(FLAG_Z);
|
self.clear_flag(FLAG_Z);
|
||||||
}
|
}
|
||||||
cycles = 4;
|
4
|
||||||
},
|
},
|
||||||
0xC1 => {
|
0xC1 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
@ -788,7 +684,7 @@ impl CPU {
|
|||||||
let val: u16 = self.interconnect.read_word(self.sp);
|
let val: u16 = self.interconnect.read_word(self.sp);
|
||||||
self.sp += 2;
|
self.sp += 2;
|
||||||
self.set_pair_value(REG_B, REG_C, val);
|
self.set_pair_value(REG_B, REG_C, val);
|
||||||
cycles = 12;
|
12
|
||||||
},
|
},
|
||||||
0xC2 => {
|
0xC2 => {
|
||||||
let addr: u16 = to_u16(self.load_args(2));
|
let addr: u16 = to_u16(self.load_args(2));
|
||||||
@ -797,9 +693,9 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
if self.flags & FLAG_Z == 0 {
|
if self.flags & FLAG_Z == 0 {
|
||||||
self.ip = addr;
|
self.ip = addr;
|
||||||
cycles = 16;
|
16
|
||||||
} else {
|
} else {
|
||||||
cycles = 12;
|
12
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0xC3 => {
|
0xC3 => {
|
||||||
@ -808,7 +704,7 @@ impl CPU {
|
|||||||
println!("JP {:04X}", addr);
|
println!("JP {:04X}", addr);
|
||||||
}
|
}
|
||||||
self.ip = addr;
|
self.ip = addr;
|
||||||
cycles = 16;
|
16
|
||||||
}
|
}
|
||||||
0xC4 => {
|
0xC4 => {
|
||||||
let target = to_u16(self.load_args(2));
|
let target = to_u16(self.load_args(2));
|
||||||
@ -817,36 +713,28 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
if self.flags & FLAG_Z == 0 {
|
if self.flags & FLAG_Z == 0 {
|
||||||
// Push current IP to the stack
|
// Push current IP to the stack
|
||||||
self.interconnect.write_word(self.sp - 1, self.ip);
|
let ip = self.ip;
|
||||||
self.sp -= 2;
|
self.push(ip);
|
||||||
self.ip = target;
|
self.ip = target;
|
||||||
cycles = 24;
|
24
|
||||||
} else {
|
} else {
|
||||||
cycles = 12;
|
12
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0xC5 => {
|
0xC5 => self.push_rr(REG_B, REG_C),
|
||||||
if self.debug {
|
|
||||||
println!("PUSH BC");
|
|
||||||
}
|
|
||||||
let val: u16 = self.get_pair_value(REG_B, REG_C);
|
|
||||||
self.interconnect.write_word(self.sp - 2, val);
|
|
||||||
self.sp -= 2;
|
|
||||||
cycles = 16;
|
|
||||||
},
|
|
||||||
0xC9 => {
|
0xC9 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("RET");
|
println!("RET");
|
||||||
}
|
|
||||||
self.dump_stack();
|
self.dump_stack();
|
||||||
|
}
|
||||||
self.ip = self.interconnect.read_word(self.sp+1);
|
self.ip = self.interconnect.read_word(self.sp+1);
|
||||||
self.sp += 2;
|
self.sp += 2;
|
||||||
cycles = 16;
|
16
|
||||||
},
|
},
|
||||||
0xCB => {
|
0xCB => {
|
||||||
// Prefix CB. This is annoying.
|
// Prefix CB. This is annoying.
|
||||||
self.run_prefix_instruction();
|
self.run_prefix_instruction();
|
||||||
cycles = 12; // TODO: Verify that this is the case for all prefix instructions.
|
12 // TODO: Verify that this is the case for all prefix instructions.
|
||||||
},
|
},
|
||||||
0xCC => {
|
0xCC => {
|
||||||
let target = to_u16(self.load_args(2));
|
let target = to_u16(self.load_args(2));
|
||||||
@ -858,9 +746,9 @@ impl CPU {
|
|||||||
self.interconnect.write_word(self.sp - 1, self.ip);
|
self.interconnect.write_word(self.sp - 1, self.ip);
|
||||||
self.sp -= 2;
|
self.sp -= 2;
|
||||||
self.ip = target;
|
self.ip = target;
|
||||||
cycles = 24;
|
24
|
||||||
} else {
|
} else {
|
||||||
cycles = 12;
|
12
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0xCD => {
|
0xCD => {
|
||||||
@ -872,7 +760,7 @@ impl CPU {
|
|||||||
self.interconnect.write_word(self.sp - 1, self.ip);
|
self.interconnect.write_word(self.sp - 1, self.ip);
|
||||||
self.sp -= 2;
|
self.sp -= 2;
|
||||||
self.ip = target;
|
self.ip = target;
|
||||||
cycles = 24;
|
24
|
||||||
},
|
},
|
||||||
0xE0 => {
|
0xE0 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
@ -880,7 +768,7 @@ impl CPU {
|
|||||||
println!("LDH {:02X}, A", args[0]);
|
println!("LDH {:02X}, A", args[0]);
|
||||||
}
|
}
|
||||||
self.interconnect.write_byte(0xFF00 + args[0] as u16, self.regs[REG_A]);
|
self.interconnect.write_byte(0xFF00 + args[0] as u16, self.regs[REG_A]);
|
||||||
cycles = 12;
|
12
|
||||||
},
|
},
|
||||||
0xE2 => {
|
0xE2 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
@ -888,7 +776,7 @@ impl CPU {
|
|||||||
println!("[{:04X}] = {:02X}", 0xFF00 + self.regs[REG_C] as u16, self.regs[REG_A]);
|
println!("[{:04X}] = {:02X}", 0xFF00 + self.regs[REG_C] as u16, self.regs[REG_A]);
|
||||||
}
|
}
|
||||||
self.interconnect.write_byte(0xFF00 + self.regs[REG_C] as u16, self.regs[REG_A]);
|
self.interconnect.write_byte(0xFF00 + self.regs[REG_C] as u16, self.regs[REG_A]);
|
||||||
cycles = 8;
|
8
|
||||||
},
|
},
|
||||||
0xEA => {
|
0xEA => {
|
||||||
let addr = to_u16(self.load_args(2));
|
let addr = to_u16(self.load_args(2));
|
||||||
@ -896,7 +784,7 @@ impl CPU {
|
|||||||
println!("LD ({:04X}), A", addr);
|
println!("LD ({:04X}), A", addr);
|
||||||
}
|
}
|
||||||
self.interconnect.write_byte(addr, self.regs[REG_A]);
|
self.interconnect.write_byte(addr, self.regs[REG_A]);
|
||||||
cycles = 16;
|
16
|
||||||
}
|
}
|
||||||
0xF0 => {
|
0xF0 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
@ -904,21 +792,21 @@ impl CPU {
|
|||||||
println!("LDH A, {:02X}", args[0]);
|
println!("LDH A, {:02X}", args[0]);
|
||||||
}
|
}
|
||||||
self.regs[REG_A] = self.interconnect.read_byte(0xFF00 + args[0] as u16);
|
self.regs[REG_A] = self.interconnect.read_byte(0xFF00 + args[0] as u16);
|
||||||
cycles = 12;
|
12
|
||||||
},
|
},
|
||||||
0xF2 => {
|
0xF2 => {
|
||||||
if self.debug{
|
if self.debug{
|
||||||
println!("LD A, (C)");
|
println!("LD A, (C)");
|
||||||
}
|
}
|
||||||
self.regs[REG_A] = self.interconnect.read_byte(0xFF00 + self.regs[REG_C] as u16);
|
self.regs[REG_A] = self.interconnect.read_byte(0xFF00 + self.regs[REG_C] as u16);
|
||||||
cycles = 8;
|
8
|
||||||
},
|
},
|
||||||
0xF3 => {
|
0xF3 => {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("DI");
|
println!("DI");
|
||||||
}
|
}
|
||||||
self.interrupts_enabled = false;
|
self.interrupts_enabled = false;
|
||||||
cycles = 4;
|
4
|
||||||
}
|
}
|
||||||
0xFB => {
|
0xFB => {
|
||||||
// Enable interrupts - TODO
|
// Enable interrupts - TODO
|
||||||
@ -926,8 +814,8 @@ impl CPU {
|
|||||||
println!("EI");
|
println!("EI");
|
||||||
}
|
}
|
||||||
self.interrupts_enabled = true;
|
self.interrupts_enabled = true;
|
||||||
cycles = 4;
|
|
||||||
panic!("ENABLING INTERRUPTS - TODO");
|
panic!("ENABLING INTERRUPTS - TODO");
|
||||||
|
4
|
||||||
},
|
},
|
||||||
0xFE => {
|
0xFE => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
@ -947,10 +835,10 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO H
|
// TODO H
|
||||||
cycles = 8;
|
8
|
||||||
}
|
}
|
||||||
_ => panic!("Unknown instruction: {:02x}", instruction)
|
_ => panic!("Unknown instruction: {:02x}", instruction)
|
||||||
}
|
};
|
||||||
// self.dump_stack();
|
// self.dump_stack();
|
||||||
self.interconnect.tick(cycles);
|
self.interconnect.tick(cycles);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,7 +70,7 @@ impl Display {
|
|||||||
let sdl_ctx = sdl2::init().unwrap();
|
let sdl_ctx = sdl2::init().unwrap();
|
||||||
let video_ctx = sdl_ctx.video().unwrap();
|
let video_ctx = sdl_ctx.video().unwrap();
|
||||||
let wnd = video_ctx.window("RustBoy", (GB_PIXELS_X * SCALE) as u32, (GB_PIXELS_Y * SCALE) as u32).position_centered().build().expect("Failed to create window :<");
|
let wnd = video_ctx.window("RustBoy", (GB_PIXELS_X * SCALE) as u32, (GB_PIXELS_Y * SCALE) as u32).position_centered().build().expect("Failed to create window :<");
|
||||||
let mut renderer = wnd.renderer().build().expect("Could not build renderer");
|
let renderer = wnd.renderer().build().expect("Could not build renderer");
|
||||||
|
|
||||||
Display {
|
Display {
|
||||||
control: 0,
|
control: 0,
|
||||||
@ -199,7 +199,25 @@ impl Display {
|
|||||||
|
|
||||||
// Render background
|
// Render background
|
||||||
if self.control & CTRL_BG_DISPLAY > 0 {
|
if self.control & CTRL_BG_DISPLAY > 0 {
|
||||||
print!("Drawing tiles: ");
|
|
||||||
|
// Draw borders first.
|
||||||
|
for t_x in 0 .. 160/8 {
|
||||||
|
self.renderer.set_draw_color(sdl2::pixels::Color::RGB(0xFF, 10, 0xFF));
|
||||||
|
|
||||||
|
// Awesome effects:
|
||||||
|
/*
|
||||||
|
let RX: i32 = (t_x as i32)*8 + map_offset_x as i32;
|
||||||
|
let RY: i32 = (render_y as i32) & 0xFFFFFFF8 + map_offset_y as i32;
|
||||||
|
let TS: u32 = 8u32 * (SCALE as u32);
|
||||||
|
*/
|
||||||
|
|
||||||
|
let RX: i32 = (t_x as i32)*8 + map_offset_x as i32;
|
||||||
|
let RY: i32 = ((render_y as u32) & 0xFFFFFFF8) as i32 - map_offset_y as i32;
|
||||||
|
let TS: u32 = 8u32 * (SCALE as u32);
|
||||||
|
self.renderer.draw_rect(
|
||||||
|
sdl2::rect::Rect::new(RX * SCALE as i32, RY * SCALE as i32, TS, TS)
|
||||||
|
);
|
||||||
|
}
|
||||||
// Render pixels (20 tiles)
|
// Render pixels (20 tiles)
|
||||||
for render_x in 0 .. 160 {
|
for render_x in 0 .. 160 {
|
||||||
// Absolute render coordinates
|
// Absolute render coordinates
|
||||||
@ -219,7 +237,7 @@ impl Display {
|
|||||||
// println!("vram offset: {:04X}", vram_offset);
|
// println!("vram offset: {:04X}", vram_offset);
|
||||||
if tile_id != 0 {
|
if tile_id != 0 {
|
||||||
// println!("Drawing tile {:02X}", tile_id);
|
// println!("Drawing tile {:02X}", tile_id);
|
||||||
print!("{:02X} ", tile_id);
|
// print!("{:02X} ", tile_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain tile information
|
// Obtain tile information
|
||||||
@ -230,7 +248,7 @@ impl Display {
|
|||||||
tile_base_addr = 0x0800;
|
tile_base_addr = 0x0800;
|
||||||
// This set goes from -127 to 127.
|
// This set goes from -127 to 127.
|
||||||
let s_tid: i8 = tile_id as i8;
|
let s_tid: i8 = tile_id as i8;
|
||||||
tile_id = (128 + s_tid) as u8;
|
tile_id = (128u8 as i8 + s_tid) as u8;
|
||||||
panic!("OH MY GOD, this wasn't tested yet");
|
panic!("OH MY GOD, this wasn't tested yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,9 +270,9 @@ impl Display {
|
|||||||
|
|
||||||
// Draw stuff. We're currently only in monochrome mode
|
// Draw stuff. We're currently only in monochrome mode
|
||||||
self.set_pixel(render_x, render_y, sdl2::pixels::Color::RGB(factor, factor, factor));
|
self.set_pixel(render_x, render_y, sdl2::pixels::Color::RGB(factor, factor, factor));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vblank_interrupt(&mut self) {
|
pub fn vblank_interrupt(&mut self) {
|
||||||
|
|||||||
@ -44,8 +44,8 @@ impl Interconnect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Somehow we need different timers for this.
|
// Somehow we need different timers for this.
|
||||||
pub fn tick(&mut self, cycles: u16) {
|
pub fn tick(&mut self, cycles: u8) {
|
||||||
self.display.tick(cycles * 4);
|
self.display.tick(cycles as u16 * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display_blank_interrupt(&mut self) {
|
pub fn display_blank_interrupt(&mut self) {
|
||||||
@ -138,6 +138,7 @@ impl Interconnect {
|
|||||||
self.display.write_byte(addr, val);
|
self.display.write_byte(addr, val);
|
||||||
},
|
},
|
||||||
0xFF50 => {
|
0xFF50 => {
|
||||||
|
println!("Disabling boot rom.");
|
||||||
self.disable_bootrom = val;
|
self.disable_bootrom = val;
|
||||||
},
|
},
|
||||||
0xFF56 => {
|
0xFF56 => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user