Add message loop; Implement all basic instructions

This commit is contained in:
Kevin Hamacher 2016-05-28 22:44:48 +02:00
parent 710b057f54
commit 001eb19df3
2 changed files with 247 additions and 237 deletions

View File

@ -350,10 +350,74 @@ impl CPU {
fn call(&mut self, dst: u16) { fn call(&mut self, dst: u16) {
let ip = self.ip; let ip = self.ip;
self.push(ip); self.push(ip);
self.dump_stack(); //self.dump_stack();
self.ip = dst; self.ip = dst;
} }
fn call_condition(&mut self, cond_str: String, cond: bool) -> u8 {
let dst = to_u16(self.load_args(2));
if self.debug {
println!("CALL {} {:04X}", cond_str, dst);
}
if cond {
self.call(dst);
24
} else {
12
}
}
fn ret_condition(&mut self, cond_str: String, cond: bool) -> u8 {
if self.debug {
println!("RET {}", cond_str);
}
if cond {
self.ret();
20
} else {
8
}
}
fn jmp_r(&mut self, addr: u8) {
let off: i8 = addr as i8;
if off < 0 {
self.ip -= (-off) as u16;
} else {
self.ip += off as u16;
}
}
fn jmp_r_condition(&mut self, cond_str: String, cond: bool) -> u8 {
let t = self.load_args(1)[0];
if self.debug {
println!("JR {} {:02X}", cond_str, t);
}
if cond {
self.jmp_r(t);
12
} else {
8
}
}
fn jmp_p(&mut self, addr: u16) {
self.ip = addr;
}
fn jmp_p_condition(&mut self, cond_str: String, cond: bool) -> u8 {
let t = to_u16(self.load_args(2));
if self.debug {
println!("JP {} {:04X}", cond_str, t);
}
if cond {
self.jmp_p(t);
12
} else {
8
}
}
fn rst(&mut self, val: u8) -> u8 { fn rst(&mut self, val: u8) -> u8 {
// Make sure this is correct. // Make sure this is correct.
if self.debug { if self.debug {
@ -413,7 +477,7 @@ impl CPU {
fn ld_r_r(&mut self, reg_dst: usize, reg_src: usize) -> u8 { fn ld_r_r(&mut self, reg_dst: usize, reg_src: usize) -> u8 {
if self.debug { if self.debug {
println!("LD {}, {}", REG_NAMES[reg_dst], REG_NAMES[reg_src]) // println!("LD {}, {}", REG_NAMES[reg_dst], REG_NAMES[reg_src])
} }
let sv = self.get_8bit_reg(reg_src); let sv = self.get_8bit_reg(reg_src);
self.set_8bit_reg(reg_dst, sv); self.set_8bit_reg(reg_dst, sv);
@ -427,7 +491,7 @@ impl CPU {
fn ld_r_v(&mut self, r: usize) -> u8 { fn ld_r_v(&mut self, r: usize) -> u8 {
let val: u8 = self.load_args(1)[0]; let val: u8 = self.load_args(1)[0];
if self.debug { if self.debug {
println!("LD {}, {:02X}", REG_NAMES[r], val); // println!("LD {}, {:02X}", REG_NAMES[r], val);
} }
self.set_8bit_reg(r, val); self.set_8bit_reg(r, val);
if r == REG_N_HL { if r == REG_N_HL {
@ -440,7 +504,7 @@ impl CPU {
fn ld_rr_vv(&mut self, r1: usize, r2: usize) -> u8 { fn ld_rr_vv(&mut self, r1: usize, r2: usize) -> u8 {
let val: u16 = to_u16(self.load_args(2)); let val: u16 = to_u16(self.load_args(2));
if self.debug { if self.debug {
println!("LD {}{}, {:04X}", REG_NAMES[r1], REG_NAMES[r2], val); // println!("LD {}{}, {:04X}", REG_NAMES[r1], REG_NAMES[r2], val);
} }
self.set_pair_value(r1, r2, val); self.set_pair_value(r1, r2, val);
12 12
@ -515,7 +579,7 @@ impl CPU {
fn ret(&mut self) { fn ret(&mut self) {
let new_ip: u16 = self.pop(); let new_ip: u16 = self.pop();
self.dump_stack(); //self.dump_stack();
self.ip = new_ip; self.ip = new_ip;
} }
@ -590,7 +654,9 @@ impl CPU {
0x04 => self.reg_inc(REG_N_B), 0x04 => self.reg_inc(REG_N_B),
0x05 => self.reg_dec(REG_N_B), 0x05 => self.reg_dec(REG_N_B),
0x06 => self.ld_r_v(REG_N_B), 0x06 => self.ld_r_v(REG_N_B),
0x07 => {
panic!("RLCA, not implemented");
}
0x08 => { 0x08 => {
let a: u16 = to_u16(self.load_args(2)); let a: u16 = to_u16(self.load_args(2));
if self.debug{ if self.debug{
@ -611,6 +677,9 @@ impl CPU {
0x0C => self.reg_inc(REG_N_C), 0x0C => self.reg_inc(REG_N_C),
0x0D => self.reg_dec(REG_N_C), 0x0D => self.reg_dec(REG_N_C),
0x0E => self.ld_r_v(REG_N_C), 0x0E => self.ld_r_v(REG_N_C),
0x0F => panic!("RRCA not implemented."),
0x10 => panic!("STOP 0 {:02X} not implemented.", self.load_args(1)[0]),
0x11 => self.ld_rr_vv(REG_N_D, REG_N_E), 0x11 => self.ld_rr_vv(REG_N_D, REG_N_E),
0x12 => self.ld_dref_rr_a(REG_N_D, REG_N_E), 0x12 => self.ld_dref_rr_a(REG_N_D, REG_N_E),
0x13 => self.inc_rr(REG_N_D, REG_N_E), 0x13 => self.inc_rr(REG_N_D, REG_N_E),
@ -635,16 +704,8 @@ impl CPU {
4 4
}, },
0x18 => { 0x18 => {
let args = self.load_args(1); let dst = self.load_args(1)[0];
if self.debug { self.jmp_r(dst);
println!("JR {:02X}", args[0] as i8);
}
let off: i8 = args[0] as i8;
if off < 0 {
self.ip -= (-off) as u16;
} else {
self.ip += off as u16;
}
12 12
}, },
0x19 => self.add_rr_rr(REG_N_H, REG_N_L, REG_N_D, REG_N_E), 0x19 => self.add_rr_rr(REG_N_H, REG_N_L, REG_N_D, REG_N_E),
@ -676,22 +737,11 @@ impl CPU {
self.clear_flag(FLAG_H); self.clear_flag(FLAG_H);
4 4
}, },
0x20 => { 0x20 => {
let args = self.load_args(1); let c = self.flags & FLAG_Z == 0;
if self.debug { self.jmp_r_condition("NZ".to_owned(), c)
println!("JR NZ {:02x}", args[0] as i8);
}
if self.flags & FLAG_Z == 0 {
let offset = args[0] as i8;
if offset < 0 {
self.ip -= (-offset) as u16
} else {
self.ip += offset as u16;
}
12
} else {
8
}
} }
0x21 => self.ld_rr_vv(REG_N_H, REG_N_L), 0x21 => self.ld_rr_vv(REG_N_H, REG_N_L),
0x22 => { 0x22 => {
@ -707,23 +757,10 @@ impl CPU {
0x24 => self.reg_inc(REG_N_H), 0x24 => self.reg_inc(REG_N_H),
0x25 => self.reg_dec(REG_N_H), 0x25 => self.reg_dec(REG_N_H),
0x26 => self.ld_r_v(REG_N_H), 0x26 => self.ld_r_v(REG_N_H),
0x27 => panic!("DAA not implemented!"),
0x28 => { 0x28 => {
let args = self.load_args(1); let c = self.flags & FLAG_Z > 0;
let target; self.jmp_r_condition("Z".to_owned(), c)
if (args[0] as i8) < 0 {
target = self.ip - (-(args[0] as i8)) as u16;
} else {
target = self.ip + args[0] as u16;
}
if self.debug {
println!("JR Z, {:04X}", target);
}
if self.flags & FLAG_Z > 0 {
self.ip = target;
12
} else {
8
}
}, },
0x29 => self.add_rr_rr(REG_N_H, REG_N_L, REG_N_H, REG_N_L), 0x29 => self.add_rr_rr(REG_N_H, REG_N_L, REG_N_H, REG_N_L),
0x2A => { 0x2A => {
@ -748,22 +785,11 @@ impl CPU {
self.set_flag(FLAG_H); self.set_flag(FLAG_H);
4 4
}, },
0x30 => { 0x30 => {
let args = self.load_args(1); let c = self.flags & FLAG_C == 0;
if self.debug { self.jmp_r_condition("NC".to_owned(), c)
println!("JR NC {:02x}", args[0] as i8);
}
if self.flags & FLAG_C == 0 {
let offset = args[0] as i8;
if offset < 0 {
self.ip -= (-offset) as u16
} else {
self.ip += offset as u16;
}
12
} else {
8
}
}, },
0x31 => { 0x31 => {
let args = self.load_args(2); let args = self.load_args(2);
@ -788,22 +814,11 @@ impl CPU {
} }
let sp = self.sp.wrapping_add(1); let sp = self.sp.wrapping_add(1);
self.sp = sp; self.sp = sp;
self.set_clear_flag(FLAG_Z, sp == 0);
self.set_clear_flag(FLAG_C, sp == 0);
self.clear_flag(FLAG_N);
8 8
} }
0x34 => self.reg_inc(REG_N_HL), 0x34 => self.reg_inc(REG_N_HL),
0x35 => self.reg_dec(REG_N_HL), 0x35 => self.reg_dec(REG_N_HL),
0x36 => { 0x36 => self.ld_r_v(REG_N_HL),
let args = self.load_args(1);
if self.debug {
println!("LD (HL), {:02x}", args[0]);
}
let addr = self.get_pair_value(REG_N_H, REG_N_L);
self.interconnect.write_byte(addr, args[0]);
12
},
0x37 => { 0x37 => {
if self.debug { if self.debug {
println!("SCF"); println!("SCF");
@ -814,21 +829,8 @@ impl CPU {
4 4
}, },
0x38 => { 0x38 => {
let args = self.load_args(1); let c = self.flags & FLAG_C > 0;
if self.debug { self.jmp_r_condition("C".to_owned(), c)
println!("JR C {:02x}", args[0] as i8);
}
if self.flags & FLAG_C > 0 {
let offset = args[0] as i8;
if offset < 0 {
self.ip -= (-offset) as u16
} else {
self.ip += offset as u16;
}
12
} else {
8
}
}, },
0x39 => { 0x39 => {
if self.debug { if self.debug {
@ -841,18 +843,17 @@ impl CPU {
self.clear_flag(FLAG_N); self.clear_flag(FLAG_N);
self.set_clear_flag(FLAG_C, old > v); self.set_clear_flag(FLAG_C, old > v);
// TODO: H-carry flag
8 8
}, },
0x3A => panic!("LD A, (HL-) not implemented"),
0x3B => { 0x3B => {
if self.debug { if self.debug {
println!("DEC SP"); println!("DEC SP");
} }
let sp = self.sp.wrapping_sub(1); let sp = self.sp.wrapping_sub(1);
self.sp = sp; self.sp = sp;
self.set_clear_flag(FLAG_Z, sp == 0);
self.set_clear_flag(FLAG_C, sp == 0xFFFF);
self.set_flag(FLAG_N);
8 8
} }
0x3C => self.reg_inc(REG_N_A), 0x3C => self.reg_inc(REG_N_A),
@ -965,11 +966,9 @@ impl CPU {
} }
self.regs[REG_A] &= self.get_8bit_reg(reg_id); self.regs[REG_A] &= self.get_8bit_reg(reg_id);
self.clear_flag(FLAG_N); self.clear_flag(FLAG_N);
if self.regs[REG_A] == 0 {
self.set_flag(FLAG_Z); let v = self.regs[REG_A];
} else { self.set_clear_flag(FLAG_Z, v == 0);
self.clear_flag(FLAG_Z);
}
self.clear_flag(FLAG_N); self.clear_flag(FLAG_N);
self.set_flag(FLAG_H); self.set_flag(FLAG_H);
self.clear_flag(FLAG_C); self.clear_flag(FLAG_C);
@ -983,11 +982,8 @@ impl CPU {
println!("XOR {}", REG_NAMES[reg_id]); println!("XOR {}", REG_NAMES[reg_id]);
} }
self.regs[REG_A] ^= self.get_8bit_reg(reg_id); self.regs[REG_A] ^= self.get_8bit_reg(reg_id);
if self.regs[REG_A] == 0 { let v = self.regs[REG_A];
self.set_flag(FLAG_Z); self.set_clear_flag(FLAG_Z, v == 0);
} else {
self.set_flag(FLAG_Z);
}
self.clear_flag(FLAG_C); self.clear_flag(FLAG_C);
self.clear_flag(FLAG_N); self.clear_flag(FLAG_N);
@ -1023,137 +1019,101 @@ impl CPU {
self.set_flag(FLAG_N); self.set_flag(FLAG_N);
self.set_clear_flag(FLAG_C, rval < val); self.set_clear_flag(FLAG_C, rval < val);
self.set_clear_flag(FLAG_Z, rval == val); self.set_clear_flag(FLAG_Z, rval == val);
// TODO H
4 4
}, },
0xC0 => { 0xC0 => {
if self.debug { let c = self.flags & FLAG_Z == 0;
println!("RET NZ"); self.ret_condition("NZ".to_owned(), c)
}
if self.flags & FLAG_Z == 0 {
self.ret();
20
} else {
8
}
}, },
0xC1 => self.pop_rr(REG_N_B, REG_N_C), 0xC1 => self.pop_rr(REG_N_B, REG_N_C),
0xC2 => { 0xC2 => {
let addr: u16 = to_u16(self.load_args(2)); let c = self.flags & FLAG_Z == 0;
if self.debug { self.jmp_p_condition("NZ".to_owned(), c)
println!("JP NZ {:04X}", addr);
}
if self.flags & FLAG_Z == 0 {
self.ip = addr;
16
} else {
12
}
}, },
0xC3 => { 0xC3 => {
let addr: u16 = to_u16(self.load_args(2)); let dst = to_u16(self.load_args(2));
if self.debug { self.jmp_p(dst);
println!("JP {:04X}", addr);
}
self.ip = addr;
16 16
}
0xC4 => {
let target = to_u16(self.load_args(2));
if self.debug {
println!("CALL NZ {:04X}", &target);
}
if self.flags & FLAG_Z == 0 {
self.call(target);
24
} else {
12
}
}, },
0xC4 => {
let c = self.flags & FLAG_Z == 0;
self.call_condition("NZ".to_owned(), c)
}
0xC5 => self.push_rr(REG_N_B, REG_N_C), 0xC5 => self.push_rr(REG_N_B, REG_N_C),
0xC6 => { 0xC6 => {
let val = self.load_args(1)[0]; let val = self.load_args(1)[0];
if self.debug { if self.debug {
println!("ADD {:02X}", val); println!("ADD A, {:02X}", val);
} }
self.regs[REG_A] = self.regs[REG_A].wrapping_add(val); let o = self.regs[REG_A];
let v = self.regs[REG_A].wrapping_add(val);
self.regs[REG_A] = v;
self.set_clear_flag(FLAG_Z, v == 0);
self.set_clear_flag(FLAG_C, v < o);
self.clear_flag(FLAG_N);
// TOOD H
8 8
}, },
0xC7 => self.rst(0x00), 0xC7 => self.rst(0x00),
0xC8 => { 0xC8 => {
if self.debug { let c = self.flags & FLAG_Z > 0;
println!("RET Z"); self.ret_condition("Z".to_owned(), c)
}
if self.flags & FLAG_Z > 0 {
self.ret();
20
} else {
8
}
},
0xC9 => {
if self.debug {
println!("RET");
}
let new_ip: u16 = self.pop();
self.ip = new_ip;
16
}, },
0xC9 => {self.ret(); 16},
0xCA => {
let c = self.flags & FLAG_Z > 0;
self.jmp_p_condition("Z".to_owned(), c)
}
0xCB => { 0xCB => {
// Prefix CB. This is annoying. // Prefix CB. This is annoying.
self.run_prefix_instruction(); self.run_prefix_instruction();
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 c = self.flags & FLAG_Z > 0;
if self.debug { self.call_condition("Z".to_owned(), c)
println!("CALL Z {:04X}", &target);
}
if self.flags & FLAG_Z > 0 {
self.call(target);
24
} else {
12
}
},
0xCD => {
let target = to_u16(self.load_args(2));
if self.debug {
println!("CALL {:04X}", &target);
}
self.call(target);
24
}, },
0xCD => self.call_condition("".to_owned(), true),
0xCE => { 0xCE => {
let arg = self.load_args(1)[0]; let arg = self.load_args(1)[0];
if self.debug { if self.debug {
println!("ADC {:02X}", arg); println!("ADC A, {:02X}", arg);
} }
self.regs[REG_A] = self.regs[REG_A].wrapping_add(arg); let o = self.regs[REG_A];
let mut v = self.regs[REG_A].wrapping_add(arg);
if self.flags & FLAG_C > 0 { if self.flags & FLAG_C > 0 {
self.regs[REG_A] = self.regs[REG_A].wrapping_add(1); v = v.wrapping_add(1);
}
if self.regs[REG_A] == 0 {
self.set_flag(FLAG_Z);
} else {
self.clear_flag(FLAG_Z);
} }
self.regs[REG_A] = v;
self.set_clear_flag(FLAG_Z, v == 0);
self.clear_flag(FLAG_N); self.clear_flag(FLAG_N);
// TODO: FLAG_H, FLAG_C self.set_clear_flag(FLAG_C, v < o);
// TODO: FLAG_H
8 8
}, },
0xCF => self.rst(0x08), 0xCF => self.rst(0x08),
0xD0 => { 0xD0 => {
if self.debug { let c = self.flags & FLAG_C == 0;
println!("RET NC"); self.ret_condition("NC".to_owned(), c)
}
if self.flags & FLAG_C == 0 {
self.ret();
20
} else {
8
}
}, },
0xD1 => self.pop_rr(REG_N_D, REG_N_E), 0xD1 => self.pop_rr(REG_N_D, REG_N_E),
0xD2 => {
let c = self.flags & FLAG_C == 0;
self.jmp_p_condition("NC".to_owned(), c)
}
0xD3 => panic!("NON-EXISTING OPCODE"),
0xD4 => {
let c = self.flags & FLAG_C == 0;
self.call_condition("NC".to_owned(), c)
}
0xD5 => self.push_rr(REG_N_D, REG_N_E), 0xD5 => self.push_rr(REG_N_D, REG_N_E),
0xD6 => { 0xD6 => {
let val = self.load_args(1)[0]; let val = self.load_args(1)[0];
@ -1167,40 +1127,46 @@ impl CPU {
self.set_flag(FLAG_N); self.set_flag(FLAG_N);
self.regs[REG_A] = rval.wrapping_sub(val); self.regs[REG_A] = rval.wrapping_sub(val);
// TODO: FLAG_H
8 8
}, },
0xD7 => self.rst(0x10), 0xD7 => self.rst(0x10),
0xD8 => { 0xD8 => {
if self.debug { let c = self.flags & FLAG_C > 0;
println!("RET C"); self.ret_condition("C".to_owned(), c)
}
if self.flags & FLAG_C > 0 {
self.ret();
20
} else {
8
}
}, },
0xD9 => self.reti(), 0xD9 => self.reti(),
0xDA => {
let c = self.flags & FLAG_C > 0;
self.jmp_p_condition("C".to_owned(), c)
},
0xDB => panic!("NON-EXISTING OPCODE"),
0xDC => {
let c = self.flags & FLAG_C > 0;
self.call_condition("C".to_owned(), c)
}
0xDD => panic!("NON-EXISTING OPCODE"),
0xDE => { 0xDE => {
let arg = self.load_args(1)[0]; let arg = self.load_args(1)[0];
if self.debug { if self.debug {
println!("SBC {:02X}", arg); println!("SBC {:02X}", arg);
} }
self.regs[REG_A] = self.regs[REG_A].wrapping_sub(arg); let o = self.regs[REG_A];
let mut v = self.regs[REG_A].wrapping_sub(arg);
if self.flags & FLAG_C > 0 { if self.flags & FLAG_C > 0 {
self.regs[REG_A] = self.regs[REG_A].wrapping_sub(1); v = v.wrapping_sub(1);
}
if self.regs[REG_A] == 0 {
self.set_flag(FLAG_Z);
} else {
self.clear_flag(FLAG_Z);
} }
self.regs[REG_A] = v;
self.set_clear_flag(FLAG_Z, v == 0);
self.set_clear_flag(FLAG_C, v > o);
self.set_flag(FLAG_N); self.set_flag(FLAG_N);
// TODO: FLAG_H, FLAG_C // TODO: FLAG_H
8 8
}, },
0xDF => self.rst(0x18), 0xDF => self.rst(0x18),
0xE0 => { 0xE0 => {
let args = self.load_args(1); let args = self.load_args(1);
if self.debug { if self.debug {
@ -1214,17 +1180,24 @@ impl CPU {
if self.debug { if self.debug {
println!("LD (C), A"); println!("LD (C), A");
} }
let addr = 0xFF00 + self.get_8bit_reg(REG_N_C); let addr: u16 = 0xFF00 + self.get_8bit_reg(REG_N_C) as u16;
self.interconnect.write_byte(0xFF00 + addr as u16, self.regs[REG_A]); self.interconnect.write_byte(addr, self.regs[REG_A]);
8 8
}, },
0xE3 | 0xE4 => panic!("NON-EXISTING OPCODE"),
0xE5 => self.push_rr(REG_N_H, REG_N_L), 0xE5 => self.push_rr(REG_N_H, REG_N_L),
0xE6 => { 0xE6 => {
let val = self.load_args(1)[0]; let val = self.load_args(1)[0];
if self.debug { if self.debug {
println!("AND {:02X}", val); println!("AND {:02X}", val);
} }
self.regs[REG_A] &= val; let v = self.regs[REG_A] & val;
self.regs[REG_A] = v;
self.set_clear_flag(FLAG_Z, v == 0);
self.clear_flag(FLAG_N);
self.set_flag(FLAG_H);
self.clear_flag(FLAG_C);
8 8
}, },
0xE7 => self.rst(0x20), 0xE7 => self.rst(0x20),
@ -1238,6 +1211,7 @@ impl CPU {
self.clear_flag(FLAG_N); self.clear_flag(FLAG_N);
self.clear_flag(FLAG_Z); self.clear_flag(FLAG_Z);
self.set_clear_flag(FLAG_C, t < sp); self.set_clear_flag(FLAG_C, t < sp);
// TODO FLAG_H
self.sp = t; self.sp = t;
16 16
} }
@ -1245,8 +1219,7 @@ impl CPU {
if self.debug { if self.debug {
println!("JP (HL)"); println!("JP (HL)");
} }
let new_ip = (self.ip as i16 + self.get_8bit_reg(REG_N_HL) as i16) as u16; self.ip = self.get_pair_value(REG_N_H, REG_N_L);
self.ip = new_ip;
4 4
}, },
0xEA => { 0xEA => {
@ -1257,23 +1230,22 @@ impl CPU {
self.interconnect.write_byte(addr, self.regs[REG_A]); self.interconnect.write_byte(addr, self.regs[REG_A]);
16 16
}, },
0xEB ... 0xED => panic!("NON-EXISTING OPCODE"),
0xEE => { 0xEE => {
let arg = self.load_args(1)[0]; let arg = self.load_args(1)[0];
if self.debug { if self.debug {
println!("XOR {:02X}", arg); println!("XOR {:02X}", arg);
} }
self.regs[REG_A] ^= arg; let v = self.regs[REG_A] ^ arg;
if self.regs[REG_A] == 0 { self.regs[REG_A] = v;
self.set_flag(FLAG_Z); self.set_clear_flag(FLAG_Z, v == 0);
} else {
self.clear_flag(FLAG_Z);
}
self.clear_flag(FLAG_H); self.clear_flag(FLAG_H);
self.clear_flag(FLAG_C); self.clear_flag(FLAG_C);
self.clear_flag(FLAG_N); self.clear_flag(FLAG_N);
8 8
}, },
0xEF => self.rst(0x28), 0xEF => self.rst(0x28),
0xF0 => { 0xF0 => {
let args = self.load_args(1); let args = self.load_args(1);
if self.debug { if self.debug {
@ -1298,45 +1270,65 @@ impl CPU {
self.ime = false; self.ime = false;
4 4
}, },
0xF4 => panic!("NON-EXISTING OPCODE"),
0xF5 => self.push_rr(REG_N_A, REG_N_F), 0xF5 => self.push_rr(REG_N_A, REG_N_F),
0xF6 => { 0xF6 => {
let val = self.load_args(1)[0]; let val = self.load_args(1)[0];
if self.debug { if self.debug {
println!("OR {:02X}", val); println!("OR {:02X}", val);
} }
self.regs[REG_A] |= val; let v = self.regs[REG_A] | val;
self.regs[REG_A] = v;
self.set_clear_flag(FLAG_Z, v == 0);
self.clear_flag(FLAG_C);
self.clear_flag(FLAG_N);
self.clear_flag(FLAG_H);
8 8
}, },
0xF7 => self.rst(0x30), 0xF7 => self.rst(0x30),
0xF8 => { 0xF8 => {
let arg = self.load_args(1)[0]; let arg = self.load_args(1)[0] as i16;
if self.debug { if self.debug {
println!("LD HL, SP+{:02X}", arg); println!("LD HL, SP+{:02X}", arg);
} }
let v = self.sp.wrapping_add(arg as u16); if arg < 0 {
let v: u16 = self.sp.wrapping_sub((-arg) as u16);
self.set_pair_value(REG_N_H, REG_N_L, v);
} else {
let v: u16 = self.sp.wrapping_add(arg as u16);
self.set_pair_value(REG_N_H, REG_N_L, v);
}
self.clear_flag(FLAG_N); self.clear_flag(FLAG_N);
self.clear_flag(FLAG_Z); self.clear_flag(FLAG_Z);
self.set_pair_value(REG_N_H, REG_N_L, v); // TODO: FLAG_H FLAG_C
12 12
} },
0xF9 => {
if self.debug {
println!("LD SP, HL");
}
self.sp = self.get_pair_value(REG_N_H, REG_N_L);
8
},
0xFA => {
let addr = to_u16(self.load_args(2));
if self.debug {
println!("LD A, ({:04X})", addr);
}
self.regs[REG_A] = self.interconnect.read_byte(addr);
16
},
0xFB => { 0xFB => {
// Enable interrupts - TODO // Enable interrupts - TODO
if self.debug { if self.debug {
println!("EI"); println!("EI");
} }
self.ime = true; // interrupt master enable //self.ime = true; // interrupt master enable
4 4
}, },
0xFA => { 0xFC | 0xFD => panic!("NON-EXISTING OPCODE"),
let addr: u16 = to_u16(self.load_args(2));
if self.debug {
println!("LD A, ({:04X})", addr);
}
let val: u8 = self.interconnect.read_byte(addr);
self.set_8bit_reg(REG_N_A, val);
16
},
0xFE => { 0xFE => {
let args = self.load_args(1); let args = self.load_args(1);
let rval = self.regs[REG_A]; let rval = self.regs[REG_A];

View File

@ -1,6 +1,9 @@
extern crate sdl2; extern crate sdl2;
extern crate libc; extern crate libc;
use self::sdl2::event::Event;
use self::sdl2::keyboard::Keycode;
// Internal ram size // Internal ram size
const VRAM_SIZE: usize = 0x2000; const VRAM_SIZE: usize = 0x2000;
@ -64,6 +67,8 @@ pub struct Display {
renderer: sdl2::render::Renderer<'static>, renderer: sdl2::render::Renderer<'static>,
event_pump: sdl2::EventPump,
vblank_fired: bool, vblank_fired: bool,
stat_fired: bool, stat_fired: bool,
vblank_interrupt: bool, vblank_interrupt: bool,
@ -76,6 +81,7 @@ impl Display {
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 renderer = wnd.renderer().build().expect("Could not build renderer"); let renderer = wnd.renderer().build().expect("Could not build renderer");
let mut event_pump = sdl_ctx.event_pump().expect("Getting event pump failed");
Display { Display {
control: 0, control: 0,
@ -96,6 +102,8 @@ impl Display {
oam: vec![0; OAM_SIZE].into_boxed_slice(), oam: vec![0; OAM_SIZE].into_boxed_slice(),
renderer: renderer, renderer: renderer,
event_pump: event_pump,
vblank_fired: false, vblank_fired: false,
stat_fired: false, stat_fired: false,
vblank_interrupt: false, vblank_interrupt: false,
@ -234,6 +242,16 @@ impl Display {
} else { } else {
self.status &= !(1 << 2); self.status &= !(1 << 2);
} }
// Make sure the window is responsive:
for event in self.event_pump.poll_iter() {
match event {
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
panic!("TODO: Proper shutdown");
},
_ => {}
}
}
} }
fn renderscan(&mut self) { fn renderscan(&mut self) {