cleanup
This commit is contained in:
parent
ea81305272
commit
79d2c99c06
431
src/cpu.rs
431
src/cpu.rs
@ -26,6 +26,7 @@ pub struct CPU {
|
|||||||
interconnect: interconnect::Interconnect,
|
interconnect: interconnect::Interconnect,
|
||||||
|
|
||||||
interrupts_enabled: bool,
|
interrupts_enabled: bool,
|
||||||
|
debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_u16(bytes: Box<[u8]>) -> u16 {
|
fn to_u16(bytes: Box<[u8]>) -> u16 {
|
||||||
@ -43,6 +44,7 @@ impl CPU {
|
|||||||
sp: 0xFFFE,
|
sp: 0xFFFE,
|
||||||
interconnect: interconnect,
|
interconnect: interconnect,
|
||||||
interrupts_enabled: false, // Is this correct?
|
interrupts_enabled: false, // Is this correct?
|
||||||
|
debug: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,14 +93,18 @@ impl CPU {
|
|||||||
0x10 ... 0x17 => {
|
0x10 ... 0x17 => {
|
||||||
let reg_id = (instruction - 0x10) as usize;
|
let reg_id = (instruction - 0x10) as usize;
|
||||||
let val = self.get_8bit_reg(reg_id);
|
let val = self.get_8bit_reg(reg_id);
|
||||||
println!("RL {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("RL {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[REG_A].rotate_left(val as u32);
|
self.regs[REG_A].rotate_left(val as u32);
|
||||||
}
|
}
|
||||||
0x40 ... 0x47 => {
|
0x40 ... 0x47 => {
|
||||||
// Test 0th bit
|
// Test 0th bit
|
||||||
let reg_id = (instruction - 0x40) as usize;
|
let reg_id = (instruction - 0x40) as usize;
|
||||||
let reg_content = self.get_8bit_reg(reg_id);
|
let reg_content = self.get_8bit_reg(reg_id);
|
||||||
println!("BIT 0, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("BIT 0, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
if reg_content & (1 << 0) == 0 {
|
if reg_content & (1 << 0) == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.flags |= FLAG_Z;
|
||||||
} else {
|
} else {
|
||||||
@ -109,7 +115,9 @@ impl CPU {
|
|||||||
// Test 1th bit
|
// Test 1th bit
|
||||||
let reg_id = (instruction - 0x48) as usize;
|
let reg_id = (instruction - 0x48) as usize;
|
||||||
let reg_content = self.get_8bit_reg(reg_id);
|
let reg_content = self.get_8bit_reg(reg_id);
|
||||||
println!("BIT 1, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("BIT 1, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
if reg_content & (1 << 1) == 0 {
|
if reg_content & (1 << 1) == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.flags |= FLAG_Z;
|
||||||
} else {
|
} else {
|
||||||
@ -120,7 +128,9 @@ impl CPU {
|
|||||||
// Test 2th bit
|
// Test 2th bit
|
||||||
let reg_id = (instruction - 0x50) as usize;
|
let reg_id = (instruction - 0x50) as usize;
|
||||||
let reg_content = self.get_8bit_reg(reg_id);
|
let reg_content = self.get_8bit_reg(reg_id);
|
||||||
println!("BIT 2, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("BIT 2, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
if reg_content & (1 << 2) == 0 {
|
if reg_content & (1 << 2) == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.flags |= FLAG_Z;
|
||||||
} else {
|
} else {
|
||||||
@ -131,7 +141,9 @@ impl CPU {
|
|||||||
// Test 3th bit
|
// Test 3th bit
|
||||||
let reg_id = (instruction - 0x58) as usize;
|
let reg_id = (instruction - 0x58) as usize;
|
||||||
let reg_content = self.get_8bit_reg(reg_id);
|
let reg_content = self.get_8bit_reg(reg_id);
|
||||||
println!("BIT 3, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("BIT 3, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
if reg_content & (1 << 3) == 0 {
|
if reg_content & (1 << 3) == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.flags |= FLAG_Z;
|
||||||
} else {
|
} else {
|
||||||
@ -142,7 +154,9 @@ impl CPU {
|
|||||||
// Test 4th bit
|
// Test 4th bit
|
||||||
let reg_id = (instruction - 0x60) as usize;
|
let reg_id = (instruction - 0x60) as usize;
|
||||||
let reg_content = self.get_8bit_reg(reg_id);
|
let reg_content = self.get_8bit_reg(reg_id);
|
||||||
println!("BIT 4, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("BIT 4, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
if reg_content & (1 << 4) == 0 {
|
if reg_content & (1 << 4) == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.flags |= FLAG_Z;
|
||||||
} else {
|
} else {
|
||||||
@ -153,7 +167,9 @@ impl CPU {
|
|||||||
// Test 5th bit
|
// Test 5th bit
|
||||||
let reg_id = (instruction - 0x68) as usize;
|
let reg_id = (instruction - 0x68) as usize;
|
||||||
let reg_content = self.get_8bit_reg(reg_id);
|
let reg_content = self.get_8bit_reg(reg_id);
|
||||||
println!("BIT 5, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("BIT 5, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
if reg_content & (1 << 5) == 0 {
|
if reg_content & (1 << 5) == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.flags |= FLAG_Z;
|
||||||
} else {
|
} else {
|
||||||
@ -164,7 +180,9 @@ impl CPU {
|
|||||||
// Test 6th bit
|
// Test 6th bit
|
||||||
let reg_id = (instruction - 0x70) as usize;
|
let reg_id = (instruction - 0x70) as usize;
|
||||||
let reg_content = self.get_8bit_reg(reg_id);
|
let reg_content = self.get_8bit_reg(reg_id);
|
||||||
println!("BIT 6, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("BIT 6, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
if reg_content & (1 << 6) == 0 {
|
if reg_content & (1 << 6) == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.flags |= FLAG_Z;
|
||||||
} else {
|
} else {
|
||||||
@ -175,7 +193,9 @@ impl CPU {
|
|||||||
// Test 7th bit
|
// Test 7th bit
|
||||||
let reg_id = (instruction - 0x78) as usize;
|
let reg_id = (instruction - 0x78) as usize;
|
||||||
let reg_content = self.get_8bit_reg(reg_id);
|
let reg_content = self.get_8bit_reg(reg_id);
|
||||||
println!("BIT 7, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("BIT 7, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
if reg_content & (1 << 7) == 0 {
|
if reg_content & (1 << 7) == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.flags |= FLAG_Z;
|
||||||
} else {
|
} else {
|
||||||
@ -221,99 +241,156 @@ impl CPU {
|
|||||||
self.flags |= FLAG_N;
|
self.flags |= FLAG_N;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_instruction(&mut self) {
|
fn set_flag(&mut self, flag: u8) {
|
||||||
let instruction = self.read_byte(self.ip);
|
self.flags |= flag;
|
||||||
print!("{:#04x}: [SP: {:#04X}] i={:02X}. ", &self.ip, &self.sp, &instruction);
|
}
|
||||||
for i in 0 .. 6 {
|
|
||||||
print!("{}: {:02X} ", REG_NAMES[i], self.get_8bit_reg(i));
|
|
||||||
}
|
|
||||||
print!("A: {:02X} ", self.regs[REG_A]);
|
|
||||||
print!("I: {:02X} ", self.interconnect.read_byte(0xFFFF));
|
|
||||||
|
|
||||||
// Flags
|
fn clear_flag(&mut self, flag: u8) {
|
||||||
print!("Z={} ", self.flags & FLAG_Z != 0);
|
self.flags &= !flag;
|
||||||
print!("N={} ", self.flags & FLAG_N != 0);
|
}
|
||||||
print!("H={} ", self.flags & FLAG_H != 0);
|
|
||||||
print!("C={} ", self.flags & FLAG_C != 0);
|
pub fn run_instruction(&mut self) {
|
||||||
|
// We need to double-check the flags
|
||||||
|
let instruction = self.read_byte(self.ip);
|
||||||
|
if self.debug {
|
||||||
|
print!("{:#04x}: [SP: {:#04X}] i={:02X}. ", &self.ip, &self.sp, &instruction);
|
||||||
|
for i in 0 .. 6 {
|
||||||
|
print!("{}: {:02X} ", REG_NAMES[i], self.get_8bit_reg(i));
|
||||||
|
}
|
||||||
|
print!("A: {:02X} ", self.regs[REG_A]);
|
||||||
|
print!("I: {:02X} ", self.interconnect.read_byte(0xFFFF));
|
||||||
|
|
||||||
|
// Flags
|
||||||
|
print!("Z={} ", self.flags & FLAG_Z != 0);
|
||||||
|
print!("N={} ", self.flags & FLAG_N != 0);
|
||||||
|
print!("H={} ", self.flags & FLAG_H != 0);
|
||||||
|
print!("C={} ", self.flags & FLAG_C != 0);
|
||||||
|
}
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
|
|
||||||
let mut cycles: u16;
|
let cycles: u16;
|
||||||
|
|
||||||
match instruction {
|
match instruction {
|
||||||
0x00 => {
|
0x00 => {
|
||||||
println!("NOP");
|
if self.debug {
|
||||||
|
println!("NOP");
|
||||||
|
}
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x01 => {
|
0x01 => {
|
||||||
println!("LD (BC), A");
|
if self.debug {
|
||||||
|
println!("LD (BC), A");
|
||||||
|
}
|
||||||
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;
|
cycles = 12;
|
||||||
}
|
},
|
||||||
|
0x02 => {
|
||||||
|
if self.debug {
|
||||||
|
println!("LD (BC),A");
|
||||||
|
}
|
||||||
|
let addr: u16 = self.get_pair_value(REG_B, REG_C);
|
||||||
|
let val: u8 = self.regs[REG_A];
|
||||||
|
self.interconnect.write_byte(addr, val);
|
||||||
|
cycles = 8;
|
||||||
|
},
|
||||||
0x04 => {
|
0x04 => {
|
||||||
println!("INC B");
|
if self.debug{
|
||||||
|
println!("INC B");
|
||||||
|
}
|
||||||
self.reg_inc(REG_B);
|
self.reg_inc(REG_B);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x05 => {
|
0x05 => {
|
||||||
println!("DEC B");
|
if self.debug {
|
||||||
|
println!("DEC B");
|
||||||
|
}
|
||||||
self.reg_dec(REG_B);
|
self.reg_dec(REG_B);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x06 => {
|
0x06 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("LD B, {:02x}", args[0]);
|
if self.debug {
|
||||||
|
println!("LD B, {:02x}", args[0]);
|
||||||
|
}
|
||||||
self.regs[REG_B] = args[0];
|
self.regs[REG_B] = args[0];
|
||||||
cycles = 8;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0x0C => {
|
0x0C => {
|
||||||
println!("INC C");
|
if self.debug {
|
||||||
|
println!("INC C");
|
||||||
|
}
|
||||||
self.reg_inc(REG_C);
|
self.reg_inc(REG_C);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x0D => {
|
0x0D => {
|
||||||
println!("DEC C");
|
if self.debug {
|
||||||
|
println!("DEC C");
|
||||||
|
}
|
||||||
self.reg_dec(REG_C);
|
self.reg_dec(REG_C);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x0E => {
|
0x0E => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("LD C, {:02x}", args[0]);
|
if self.debug {
|
||||||
|
println!("LD C, {:02x}", args[0]);
|
||||||
|
}
|
||||||
self.regs[REG_C] = args[0];
|
self.regs[REG_C] = args[0];
|
||||||
cycles = 8;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0x11 => {
|
0x11 => {
|
||||||
let args = self.load_args(2);
|
let args = self.load_args(2);
|
||||||
let val = to_u16(args);
|
let val = to_u16(args);
|
||||||
println!("LD DE, {:04x}", val);
|
if self.debug {
|
||||||
|
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;
|
cycles = 12;
|
||||||
},
|
},
|
||||||
|
0x12 => {
|
||||||
|
if self.debug {
|
||||||
|
println!("LD (DE),A");
|
||||||
|
}
|
||||||
|
let addr: u16 = self.get_pair_value(REG_D, REG_E);
|
||||||
|
let val: u8 = self.regs[REG_A];
|
||||||
|
self.interconnect.write_byte(addr, val);
|
||||||
|
cycles = 12;
|
||||||
|
},
|
||||||
0x13 => {
|
0x13 => {
|
||||||
println!("INC DE");
|
if self.debug {
|
||||||
|
println!("INC DE");
|
||||||
|
}
|
||||||
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;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0x14 => {
|
0x14 => {
|
||||||
println!("INC D");
|
if self.debug {
|
||||||
|
println!("INC D");
|
||||||
|
}
|
||||||
self.reg_inc(REG_D);
|
self.reg_inc(REG_D);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x15 => {
|
0x15 => {
|
||||||
println!("DEC D");
|
if self.debug {
|
||||||
|
println!("DEC D");
|
||||||
|
}
|
||||||
self.reg_dec(REG_D);
|
self.reg_dec(REG_D);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x16 => {
|
0x16 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("LD D, {:02x}", args[0]);
|
if self.debug {
|
||||||
|
println!("LD D, {:02x}", args[0]);
|
||||||
|
}
|
||||||
self.regs[REG_D] = args[0];
|
self.regs[REG_D] = args[0];
|
||||||
cycles = 8;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0x17 => {
|
0x17 => {
|
||||||
println!("RLA");
|
if self.debug {
|
||||||
|
println!("RLA");
|
||||||
|
}
|
||||||
let carry = self.flags & FLAG_C == FLAG_C;
|
let carry = self.flags & FLAG_C == FLAG_C;
|
||||||
if !carry {
|
if !carry {
|
||||||
// No carry before, now we got a carry => set it
|
// No carry before, now we got a carry => set it
|
||||||
@ -331,7 +408,9 @@ impl CPU {
|
|||||||
},
|
},
|
||||||
0x18 => {
|
0x18 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("JR {:02X}", args[0] as i8);
|
if self.debug {
|
||||||
|
println!("JR {:02X}", args[0] as i8);
|
||||||
|
}
|
||||||
let off: i8 = args[0] as i8;
|
let off: i8 = args[0] as i8;
|
||||||
if off < 0 {
|
if off < 0 {
|
||||||
self.ip -= (-off) as u16;
|
self.ip -= (-off) as u16;
|
||||||
@ -341,29 +420,39 @@ impl CPU {
|
|||||||
cycles = 12;
|
cycles = 12;
|
||||||
},
|
},
|
||||||
0x1A => {
|
0x1A => {
|
||||||
println!("LD A, (DE)");
|
if self.debug {
|
||||||
|
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;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0x1C => {
|
0x1C => {
|
||||||
println!("INC E");
|
if self.debug {
|
||||||
|
println!("INC E");
|
||||||
|
}
|
||||||
self.reg_inc(REG_E);
|
self.reg_inc(REG_E);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x1D => {
|
0x1D => {
|
||||||
println!("DEC E");
|
if self.debug {
|
||||||
|
println!("DEC E");
|
||||||
|
}
|
||||||
self.reg_dec(REG_E);
|
self.reg_dec(REG_E);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x1E => {
|
0x1E => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("LD E, {:02x}", args[0]);
|
if self.debug {
|
||||||
|
println!("LD E, {:02x}", args[0]);
|
||||||
|
}
|
||||||
self.regs[REG_E] = args[0];
|
self.regs[REG_E] = args[0];
|
||||||
cycles = 8;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0x20 => {
|
0x20 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("JR NZ {:02x}", args[0] as i8);
|
if self.debug {
|
||||||
|
println!("JR NZ {:02x}", args[0] as i8);
|
||||||
|
}
|
||||||
if self.flags & FLAG_Z == 0 {
|
if self.flags & FLAG_Z == 0 {
|
||||||
let offset = args[0] as i8;
|
let offset = args[0] as i8;
|
||||||
if offset < 0 {
|
if offset < 0 {
|
||||||
@ -378,48 +467,62 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
0x21 => {
|
0x21 => {
|
||||||
let value = to_u16(self.load_args(2));
|
let value = to_u16(self.load_args(2));
|
||||||
println!("LD HL, {:04x}", value);
|
if self.debug {
|
||||||
|
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;
|
cycles = 12;
|
||||||
},
|
},
|
||||||
0x22 => {
|
0x22 => {
|
||||||
println!("LD (HL+), A");
|
if self.debug {
|
||||||
|
println!("LD (HL+), A");
|
||||||
|
}
|
||||||
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;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0x23 => {
|
0x23 => {
|
||||||
println!("INC HL");
|
if self.debug {
|
||||||
|
println!("INC HL");
|
||||||
|
}
|
||||||
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;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0x24 => {
|
0x24 => {
|
||||||
println!("INC H");
|
if self.debug {
|
||||||
|
println!("INC H");
|
||||||
|
}
|
||||||
self.reg_inc(REG_H);
|
self.reg_inc(REG_H);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x25 => {
|
0x25 => {
|
||||||
println!("DEC H");
|
if self.debug {
|
||||||
|
println!("DEC H");
|
||||||
|
}
|
||||||
self.reg_dec(REG_H);
|
self.reg_dec(REG_H);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x26 => {
|
0x26 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("LD H, {:02x}", args[0]);
|
if self.debug {
|
||||||
|
println!("LD H, {:02x}", args[0]);
|
||||||
|
}
|
||||||
self.regs[REG_H] = args[0];
|
self.regs[REG_H] = args[0];
|
||||||
cycles = 8;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0x28 => {
|
0x28 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
let mut target;
|
let target;
|
||||||
if args[0] < 0 {
|
if (args[0] as i8) < 0 {
|
||||||
target = self.ip - (-(args[0] as i8)) as u16;
|
target = self.ip - (-(args[0] as i8)) as u16;
|
||||||
} else {
|
} else {
|
||||||
target = self.ip + args[0] as u16;
|
target = self.ip + args[0] as u16;
|
||||||
}
|
}
|
||||||
println!("JR Z, {:04X}", target);
|
if self.debug {
|
||||||
|
println!("JR Z, {:04X}", target);
|
||||||
|
}
|
||||||
if self.flags & FLAG_Z > 0 {
|
if self.flags & FLAG_Z > 0 {
|
||||||
self.ip = target;
|
self.ip = target;
|
||||||
cycles = 12;
|
cycles = 12;
|
||||||
@ -427,30 +530,48 @@ impl CPU {
|
|||||||
cycles = 8;
|
cycles = 8;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
0x2A => {
|
||||||
|
if self.debug {
|
||||||
|
println!("LD A, (HL+)");
|
||||||
|
}
|
||||||
|
let addr: u16 = self.get_pair_value(REG_H, REG_L);
|
||||||
|
self.regs[REG_A] = self.interconnect.read_byte(addr);
|
||||||
|
cycles = 8;
|
||||||
|
},
|
||||||
0x2C => {
|
0x2C => {
|
||||||
println!("INC L");
|
if self.debug {
|
||||||
|
println!("INC L");
|
||||||
|
}
|
||||||
self.reg_inc(REG_L);
|
self.reg_inc(REG_L);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x2D => {
|
0x2D => {
|
||||||
println!("DEC L");
|
if self.debug {
|
||||||
|
println!("DEC L");
|
||||||
|
}
|
||||||
self.reg_dec(REG_L);
|
self.reg_dec(REG_L);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x2E => {
|
0x2E => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("LD L, {:02x}", args[0]);
|
if self.debug {
|
||||||
|
println!("LD L, {:02x}", args[0]);
|
||||||
|
}
|
||||||
self.regs[REG_L] = args[0];
|
self.regs[REG_L] = args[0];
|
||||||
cycles = 8;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0x31 => {
|
0x31 => {
|
||||||
let args = self.load_args(2);
|
let args = self.load_args(2);
|
||||||
self.sp = to_u16(args);
|
self.sp = to_u16(args);
|
||||||
println!("LD SP, {:02x}", self.sp);
|
if self.debug {
|
||||||
|
println!("LD SP, {:02x}", self.sp);
|
||||||
|
}
|
||||||
cycles = 12;
|
cycles = 12;
|
||||||
},
|
},
|
||||||
0x32 => {
|
0x32 => {
|
||||||
println!("LD (HL-), A");
|
if self.debug {
|
||||||
|
println!("LD (HL-), A");
|
||||||
|
}
|
||||||
let mut addr = self.get_pair_value(REG_H, REG_L);
|
let mut addr = 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]);
|
||||||
|
|
||||||
@ -460,24 +581,32 @@ impl CPU {
|
|||||||
},
|
},
|
||||||
0x36 => {
|
0x36 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("LD (HL), {:02x}", args[0]);
|
if self.debug {
|
||||||
|
println!("LD (HL), {:02x}", args[0]);
|
||||||
|
}
|
||||||
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;
|
cycles = 12;
|
||||||
},
|
},
|
||||||
0x3C => {
|
0x3C => {
|
||||||
println!("INC A");
|
if self.debug {
|
||||||
|
println!("INC A");
|
||||||
|
}
|
||||||
self.reg_inc(REG_A);
|
self.reg_inc(REG_A);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
}
|
}
|
||||||
0x3D => {
|
0x3D => {
|
||||||
println!("DEC A");
|
if self.debug {
|
||||||
|
println!("DEC A");
|
||||||
|
}
|
||||||
self.reg_dec(REG_A);
|
self.reg_dec(REG_A);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
}
|
}
|
||||||
0x3E => {
|
0x3E => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("LD A, {:02x}", args[0]);
|
if self.debug {
|
||||||
|
println!("LD A, {:02x}", args[0]);
|
||||||
|
}
|
||||||
self.regs[REG_A] = args[0];
|
self.regs[REG_A] = args[0];
|
||||||
cycles = 8;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
@ -485,43 +614,57 @@ impl CPU {
|
|||||||
// LDs
|
// LDs
|
||||||
0x40 ... 0x47 => {
|
0x40 ... 0x47 => {
|
||||||
let reg_id = (instruction - 0x40) as usize;
|
let reg_id = (instruction - 0x40) as usize;
|
||||||
println!("LD B, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("LD B, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[REG_B] = self.get_8bit_reg(reg_id);
|
self.regs[REG_B] = self.get_8bit_reg(reg_id);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x48 ... 0x4F => {
|
0x48 ... 0x4F => {
|
||||||
let reg_id = (instruction - 0x48) as usize;
|
let reg_id = (instruction - 0x48) as usize;
|
||||||
println!("LD C, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("LD C, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[REG_C] = self.get_8bit_reg(reg_id);
|
self.regs[REG_C] = self.get_8bit_reg(reg_id);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x50 ... 0x57 => {
|
0x50 ... 0x57 => {
|
||||||
let reg_id = (instruction - 0x50) as usize;
|
let reg_id = (instruction - 0x50) as usize;
|
||||||
println!("LD D, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("LD D, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[REG_D] = self.get_8bit_reg(reg_id);
|
self.regs[REG_D] = self.get_8bit_reg(reg_id);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x58 ... 0x5F => {
|
0x58 ... 0x5F => {
|
||||||
let reg_id = (instruction - 0x58) as usize;
|
let reg_id = (instruction - 0x58) as usize;
|
||||||
println!("LD E, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("LD E, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[REG_E] = self.get_8bit_reg(reg_id);
|
self.regs[REG_E] = self.get_8bit_reg(reg_id);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x60 ... 0x67 => {
|
0x60 ... 0x67 => {
|
||||||
let reg_id = (instruction - 0x60) as usize;
|
let reg_id = (instruction - 0x60) as usize;
|
||||||
println!("LD H, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("LD H, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[REG_H] = self.get_8bit_reg(reg_id);
|
self.regs[REG_H] = self.get_8bit_reg(reg_id);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x68 ... 0x6F => {
|
0x68 ... 0x6F => {
|
||||||
let reg_id = (instruction - 0x68) as usize;
|
let reg_id = (instruction - 0x68) as usize;
|
||||||
println!("LD L, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("LD L, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[REG_L] = self.get_8bit_reg(reg_id);
|
self.regs[REG_L] = self.get_8bit_reg(reg_id);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0x70 ... 0x75 | 0x77 => {
|
0x70 ... 0x75 | 0x77 => {
|
||||||
let reg_id = (instruction - 0x70) as usize;
|
let reg_id = (instruction - 0x70) as usize;
|
||||||
println!("LD (HL), {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("LD (HL), {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
let reg_value: u8 = self.get_8bit_reg(reg_id);
|
let reg_value: u8 = self.get_8bit_reg(reg_id);
|
||||||
let addr: u16 = self.get_pair_value(REG_H, REG_L);
|
let addr: u16 = self.get_pair_value(REG_H, REG_L);
|
||||||
cycles = 8;
|
cycles = 8;
|
||||||
@ -530,7 +673,9 @@ impl CPU {
|
|||||||
},
|
},
|
||||||
0x78 ... 0x7F => {
|
0x78 ... 0x7F => {
|
||||||
let reg_id = (instruction - 0x78) as usize;
|
let reg_id = (instruction - 0x78) as usize;
|
||||||
println!("LD A, {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("LD A, {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[REG_A] = self.get_8bit_reg(reg_id);
|
self.regs[REG_A] = self.get_8bit_reg(reg_id);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
@ -538,9 +683,12 @@ impl CPU {
|
|||||||
// ADD
|
// ADD
|
||||||
0x80 ... 0x87 => {
|
0x80 ... 0x87 => {
|
||||||
let reg_id = (instruction - 0x80) as usize;
|
let reg_id = (instruction - 0x80) as usize;
|
||||||
println!("ADD {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("ADD {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
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.flags &= !FLAG_N;
|
|
||||||
|
self.clear_flag(FLAG_N);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,20 +700,23 @@ impl CPU {
|
|||||||
if self.flags & FLAG_C == FLAG_C {
|
if self.flags & FLAG_C == FLAG_C {
|
||||||
self.regs[REG_A] = self.regs[REG_A].wrapping_add(1);
|
self.regs[REG_A] = self.regs[REG_A].wrapping_add(1);
|
||||||
}
|
}
|
||||||
self.flags &= !FLAG_N;
|
|
||||||
|
self.set_flag(FLAG_N);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SUBs
|
// SUBs
|
||||||
0x90 ... 0x97 => {
|
0x90 ... 0x97 => {
|
||||||
let reg_id = (instruction - 0x90) as usize;
|
let reg_id = (instruction - 0x90) as usize;
|
||||||
println!("SUB {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("SUB {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[REG_A] = self.regs[REG_A].wrapping_sub(self.get_8bit_reg(reg_id));
|
self.regs[REG_A] = self.regs[REG_A].wrapping_sub(self.get_8bit_reg(reg_id));
|
||||||
self.flags |= FLAG_N;
|
self.set_flag(FLAG_N);
|
||||||
if self.regs[REG_A] == 0 {
|
if self.regs[REG_A] == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.set_flag(FLAG_Z);
|
||||||
} else {
|
} else {
|
||||||
self.flags &= !FLAG_Z;
|
self.clear_flag(FLAG_Z);
|
||||||
}
|
}
|
||||||
// TODO: H, C
|
// TODO: H, C
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
@ -574,50 +725,66 @@ impl CPU {
|
|||||||
// SBC
|
// SBC
|
||||||
0x98 ... 0x9F => {
|
0x98 ... 0x9F => {
|
||||||
let reg_id = (instruction - 0x98) as usize;
|
let reg_id = (instruction - 0x98) as usize;
|
||||||
println!("SBC {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("SBC {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
self.regs[REG_A] = self.regs[REG_A].wrapping_sub(self.get_8bit_reg(reg_id));
|
self.regs[REG_A] = self.regs[REG_A].wrapping_sub(self.get_8bit_reg(reg_id));
|
||||||
if self.flags & FLAG_C == FLAG_C {
|
if self.flags & FLAG_C == FLAG_C {
|
||||||
self.regs[REG_A] = self.regs[REG_A].wrapping_sub(1);
|
self.regs[REG_A] = self.regs[REG_A].wrapping_sub(1);
|
||||||
}
|
}
|
||||||
self.flags |= FLAG_N;
|
self.set_flag(FLAG_N);
|
||||||
|
if self.regs[REG_A] == 0 {
|
||||||
|
self.set_flag(FLAG_Z);
|
||||||
|
} else {
|
||||||
|
self.clear_flag(FLAG_Z);
|
||||||
|
}
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XOR
|
// XOR
|
||||||
0xA8 ... 0xAF => {
|
0xA8 ... 0xAF => {
|
||||||
let reg_id = (instruction - 0xA8) as usize;
|
let reg_id = (instruction - 0xA8) as usize;
|
||||||
println!("XOR {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
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 {
|
if self.regs[REG_A] == 0 {
|
||||||
self.flags |= FLAG_Z;
|
self.set_flag(FLAG_Z);
|
||||||
} else {
|
} else {
|
||||||
self.flags &= !FLAG_Z;
|
self.set_flag(FLAG_Z);
|
||||||
}
|
}
|
||||||
self.flags &= !FLAG_C;
|
|
||||||
self.flags &= !FLAG_N;
|
self.clear_flag(FLAG_C);
|
||||||
self.flags &= !FLAG_H;
|
self.clear_flag(FLAG_N);
|
||||||
|
self.clear_flag(FLAG_H);
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
|
|
||||||
// CP
|
// CP
|
||||||
0xB8 ... 0xBF => {
|
0xB8 ... 0xBF => {
|
||||||
let reg_id = (instruction - 0xB8) as usize;
|
let reg_id = (instruction - 0xB8) as usize;
|
||||||
println!("CP {}", REG_NAMES[reg_id]);
|
if self.debug {
|
||||||
|
println!("CP {}", REG_NAMES[reg_id]);
|
||||||
|
}
|
||||||
let val = self.get_8bit_reg(reg_id);
|
let val = self.get_8bit_reg(reg_id);
|
||||||
if self.regs[REG_A] < self.get_8bit_reg(reg_id) {
|
|
||||||
self.flags |= FLAG_C;
|
self.set_flag(FLAG_N);
|
||||||
self.flags &= !FLAG_Z;
|
if self.regs[REG_A] < val {
|
||||||
} else if self.regs[REG_A] == self.get_8bit_reg(reg_id) {
|
self.set_flag(FLAG_C);
|
||||||
self.flags |= FLAG_Z;
|
self.clear_flag(FLAG_Z);
|
||||||
self.flags &= !FLAG_C;
|
} else if self.regs[REG_A] == val {
|
||||||
|
self.clear_flag(FLAG_C);
|
||||||
|
self.set_flag(FLAG_Z);
|
||||||
} else {
|
} else {
|
||||||
self.flags &= !FLAG_Z;
|
self.clear_flag(FLAG_C);
|
||||||
self.flags &= !FLAG_C;
|
self.clear_flag(FLAG_Z);
|
||||||
}
|
}
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
},
|
},
|
||||||
0xC1 => {
|
0xC1 => {
|
||||||
println!("POP BC");
|
if self.debug {
|
||||||
|
println!("POP BC");
|
||||||
|
}
|
||||||
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);
|
||||||
@ -625,7 +792,9 @@ impl CPU {
|
|||||||
},
|
},
|
||||||
0xC2 => {
|
0xC2 => {
|
||||||
let addr: u16 = to_u16(self.load_args(2));
|
let addr: u16 = to_u16(self.load_args(2));
|
||||||
println!("JP NZ {:04X}", addr);
|
if self.debug {
|
||||||
|
println!("JP NZ {:04X}", addr);
|
||||||
|
}
|
||||||
if self.flags & FLAG_Z == 0 {
|
if self.flags & FLAG_Z == 0 {
|
||||||
self.ip = addr;
|
self.ip = addr;
|
||||||
cycles = 16;
|
cycles = 16;
|
||||||
@ -635,13 +804,17 @@ impl CPU {
|
|||||||
},
|
},
|
||||||
0xC3 => {
|
0xC3 => {
|
||||||
let addr: u16 = to_u16(self.load_args(2));
|
let addr: u16 = to_u16(self.load_args(2));
|
||||||
println!("JP {:04X}", addr);
|
if self.debug {
|
||||||
|
println!("JP {:04X}", addr);
|
||||||
|
}
|
||||||
self.ip = addr;
|
self.ip = addr;
|
||||||
cycles = 16;
|
cycles = 16;
|
||||||
}
|
}
|
||||||
0xC4 => {
|
0xC4 => {
|
||||||
let target = to_u16(self.load_args(2));
|
let target = to_u16(self.load_args(2));
|
||||||
println!("CALL NZ {:04X}", &target);
|
if self.debug {
|
||||||
|
println!("CALL NZ {:04X}", &target);
|
||||||
|
}
|
||||||
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);
|
self.interconnect.write_word(self.sp - 1, self.ip);
|
||||||
@ -653,14 +826,18 @@ impl CPU {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
0xC5 => {
|
0xC5 => {
|
||||||
println!("PUSH BC");
|
if self.debug {
|
||||||
|
println!("PUSH BC");
|
||||||
|
}
|
||||||
let val: u16 = self.get_pair_value(REG_B, REG_C);
|
let val: u16 = self.get_pair_value(REG_B, REG_C);
|
||||||
self.interconnect.write_word(self.sp - 2, val);
|
self.interconnect.write_word(self.sp - 2, val);
|
||||||
self.sp -= 2;
|
self.sp -= 2;
|
||||||
cycles = 16;
|
cycles = 16;
|
||||||
},
|
},
|
||||||
0xC9 => {
|
0xC9 => {
|
||||||
println!("RET");
|
if self.debug {
|
||||||
|
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;
|
||||||
@ -673,7 +850,9 @@ impl CPU {
|
|||||||
},
|
},
|
||||||
0xCC => {
|
0xCC => {
|
||||||
let target = to_u16(self.load_args(2));
|
let target = to_u16(self.load_args(2));
|
||||||
println!("CALL Z {:04X}", &target);
|
if self.debug {
|
||||||
|
println!("CALL Z {:04X}", &target);
|
||||||
|
}
|
||||||
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);
|
self.interconnect.write_word(self.sp - 1, self.ip);
|
||||||
@ -686,7 +865,9 @@ impl CPU {
|
|||||||
},
|
},
|
||||||
0xCD => {
|
0xCD => {
|
||||||
let target = to_u16(self.load_args(2));
|
let target = to_u16(self.load_args(2));
|
||||||
println!("CALL {:04X}", &target);
|
if self.debug {
|
||||||
|
println!("CALL {:04X}", &target);
|
||||||
|
}
|
||||||
// Push current IP to the stack
|
// Push current IP to the stack
|
||||||
self.interconnect.write_word(self.sp - 1, self.ip);
|
self.interconnect.write_word(self.sp - 1, self.ip);
|
||||||
self.sp -= 2;
|
self.sp -= 2;
|
||||||
@ -695,60 +876,74 @@ impl CPU {
|
|||||||
},
|
},
|
||||||
0xE0 => {
|
0xE0 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("LDH {:02X}, A", args[0]);
|
if self.debug {
|
||||||
|
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;
|
cycles = 12;
|
||||||
},
|
},
|
||||||
0xE2 => {
|
0xE2 => {
|
||||||
println!("LD (C), A");
|
if self.debug {
|
||||||
println!("[{:04X}] = {:02X}", 0xFF00 + self.regs[REG_C] as u16, self.regs[REG_A]);
|
println!("LD (C), 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;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0xEA => {
|
0xEA => {
|
||||||
let addr = to_u16(self.load_args(2));
|
let addr = to_u16(self.load_args(2));
|
||||||
println!("LD ({:04X}), A", addr);
|
if self.debug{
|
||||||
|
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;
|
cycles = 16;
|
||||||
}
|
}
|
||||||
0xF0 => {
|
0xF0 => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("LDH A, {:02X}", args[0]);
|
if self.debug {
|
||||||
|
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;
|
cycles = 12;
|
||||||
},
|
},
|
||||||
0xF2 => {
|
0xF2 => {
|
||||||
println!("LD A, (C)");
|
if self.debug{
|
||||||
|
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;
|
cycles = 8;
|
||||||
},
|
},
|
||||||
0xF3 => {
|
0xF3 => {
|
||||||
println!("DI");
|
if self.debug {
|
||||||
|
println!("DI");
|
||||||
|
}
|
||||||
self.interrupts_enabled = false;
|
self.interrupts_enabled = false;
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
}
|
}
|
||||||
0xFB => {
|
0xFB => {
|
||||||
// Enable interrupts - TODO
|
// Enable interrupts - TODO
|
||||||
println!("EI");
|
if self.debug {
|
||||||
|
println!("EI");
|
||||||
|
}
|
||||||
self.interrupts_enabled = true;
|
self.interrupts_enabled = true;
|
||||||
// self.interconnect.write_byte(0xFFFF, 0x01);
|
|
||||||
// panic!("Uh uh");
|
|
||||||
cycles = 4;
|
cycles = 4;
|
||||||
panic!("ENABLING INTERRUPTS - TODO");
|
panic!("ENABLING INTERRUPTS - TODO");
|
||||||
},
|
},
|
||||||
0xFE => {
|
0xFE => {
|
||||||
let args = self.load_args(1);
|
let args = self.load_args(1);
|
||||||
println!("CP {:02X}", args[0]);
|
if self.debug {
|
||||||
self.flags |= FLAG_N;
|
println!("CP {:02X}", args[0]);
|
||||||
|
}
|
||||||
|
self.set_flag(FLAG_N);
|
||||||
if args[0] > self.regs[REG_A] {
|
if args[0] > self.regs[REG_A] {
|
||||||
self.flags |= FLAG_C;
|
self.set_flag(FLAG_C);
|
||||||
} else {
|
} else {
|
||||||
self.flags &= !FLAG_C;
|
self.clear_flag(FLAG_C);
|
||||||
}
|
}
|
||||||
if args[0] == self.regs[REG_A] {
|
if args[0] == self.regs[REG_A] {
|
||||||
self.flags |= FLAG_Z;
|
self.set_flag(FLAG_Z);
|
||||||
} else {
|
} else {
|
||||||
self.flags &= !FLAG_Z;
|
self.clear_flag(FLAG_Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO H
|
// TODO H
|
||||||
|
|||||||
@ -15,6 +15,16 @@ const GB_PIXELS_X: u16 = 160;
|
|||||||
const GB_PIXELS_Y: u16 = 144;
|
const GB_PIXELS_Y: u16 = 144;
|
||||||
const SCALE: u16 = 4;
|
const SCALE: u16 = 4;
|
||||||
|
|
||||||
|
// Control flags
|
||||||
|
const CTRL_LCD_DISPLAY_ENABLE: u8 = 1 << 7;
|
||||||
|
const CTRL_TILE_MAP_SELECT: u8 = 1 << 6;
|
||||||
|
const CTRL_WND_DISPLAY_ENABLE: u8 = 1 << 5;
|
||||||
|
const CTRL_BG_WINDOW_TILE_DATA_SELECT: u8 = 1 << 4;
|
||||||
|
const CTRL_BG_TILE_MAP_SELECT: u8 = 1 << 3;
|
||||||
|
const CTRL_BG_SPRITE_SIZE: u8 = 1 << 2;
|
||||||
|
const CTRL_BG_SPRITE_ENABLE: u8 = 1 << 1;
|
||||||
|
const CTRL_BG_DISPLAY: u8 = 1 << 0;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum DisplayMode {
|
enum DisplayMode {
|
||||||
Scanline,
|
Scanline,
|
||||||
@ -171,7 +181,7 @@ impl Display {
|
|||||||
// Points to the background map offset to use.
|
// Points to the background map offset to use.
|
||||||
let background_map: usize;
|
let background_map: usize;
|
||||||
// verify!
|
// verify!
|
||||||
if self.control & (1 << 3) > 0 {
|
if self.control & CTRL_BG_TILE_MAP_SELECT > 0 {
|
||||||
background_map = 0x1C00;
|
background_map = 0x1C00;
|
||||||
} else {
|
} else {
|
||||||
background_map = 0x1800;
|
background_map = 0x1800;
|
||||||
@ -183,13 +193,13 @@ impl Display {
|
|||||||
|
|
||||||
let render_y: u8 = self.curline;
|
let render_y: u8 = self.curline;
|
||||||
|
|
||||||
if self.control & (1 << 1) > 0 {
|
if self.control & CTRL_BG_SPRITE_ENABLE > 0 {
|
||||||
panic!("Switch OBJ not supported");
|
panic!("Sprites not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render background
|
// Render background
|
||||||
if self.control & (1 << 0) > 0 {
|
if self.control & CTRL_BG_DISPLAY > 0 {
|
||||||
println!("Render background");
|
print!("Drawing tiles: ");
|
||||||
// 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
|
||||||
@ -203,37 +213,24 @@ impl Display {
|
|||||||
let tile_offset_y: u8 = render_abs_y % 8;
|
let tile_offset_y: u8 = render_abs_y % 8;
|
||||||
|
|
||||||
let vram_offset: usize = background_map + (tile_index_y as usize) * 32 + tile_index_x as usize;
|
let vram_offset: usize = background_map + (tile_index_y as usize) * 32 + tile_index_x as usize;
|
||||||
|
|
||||||
// Obtain tile ID in this area
|
// Obtain tile ID in this area
|
||||||
// println!("Render absolute [{:03X}:{:03X}] -> {:03X}", render_abs_x, render_abs_y, vram_offset);
|
|
||||||
let mut tile_id = self.vram[vram_offset];
|
let mut tile_id = self.vram[vram_offset];
|
||||||
/*
|
// println!("vram offset: {:04X}", vram_offset);
|
||||||
if self.control & (1 << 4) > 0 {
|
|
||||||
// This tile dataset is from -127 to 127, not from 0 to 255
|
|
||||||
if (tile_id as i8) < 0 {
|
|
||||||
tile_id = (-(tile_id as i8)) as u8;
|
|
||||||
} else {
|
|
||||||
tile_id += 127;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain tile information
|
// Obtain tile information
|
||||||
let tile_base_addr: usize;
|
let tile_base_addr: usize;
|
||||||
if self.control & (1 << 4) > 0 {
|
if self.control & CTRL_BG_WINDOW_TILE_DATA_SELECT > 0 {
|
||||||
tile_base_addr = 0x0000;
|
tile_base_addr = 0x0000;
|
||||||
} else {
|
} else {
|
||||||
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;
|
||||||
if s_tid < 0 {
|
tile_id = (128 + s_tid) as u8;
|
||||||
tile_id = (127 + s_tid) as u8;
|
|
||||||
} else {
|
|
||||||
tile_id = tile_id + 127;
|
|
||||||
}
|
|
||||||
panic!("OH MY GOD, this wasn't tested yet");
|
panic!("OH MY GOD, this wasn't tested yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,14 +250,11 @@ impl Display {
|
|||||||
factor += 128;
|
factor += 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw stuff
|
// 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));
|
||||||
// self.set_pixel(render_x, render_y, sdl2::pixels::Color::RGB(255, 255, 255));
|
|
||||||
// let tile_base_addr = tilemap + tile_id*128
|
|
||||||
// pixel(render_x, map_offset_y) := *tile_base_addr + 2* *(tile_base_addr+1)
|
|
||||||
//[tile_index_x][tile_index_y]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vblank_interrupt(&mut self) {
|
pub fn vblank_interrupt(&mut self) {
|
||||||
|
|||||||
@ -18,7 +18,6 @@ pub struct Interconnect {
|
|||||||
display: display::Display,
|
display: display::Display,
|
||||||
interrupt: u8,
|
interrupt: u8,
|
||||||
iflags: u8,
|
iflags: u8,
|
||||||
itimer: u8,
|
|
||||||
disable_bootrom: u8,
|
disable_bootrom: u8,
|
||||||
infrared_com_port: u8,
|
infrared_com_port: u8,
|
||||||
serial: serial::Serial,
|
serial: serial::Serial,
|
||||||
@ -38,7 +37,6 @@ impl Interconnect {
|
|||||||
iflags: 0,
|
iflags: 0,
|
||||||
interrupt: 0,
|
interrupt: 0,
|
||||||
infrared_com_port: 0,
|
infrared_com_port: 0,
|
||||||
itimer: 0,
|
|
||||||
disable_bootrom: 0,
|
disable_bootrom: 0,
|
||||||
timer: timer::Timer::new(),
|
timer: timer::Timer::new(),
|
||||||
serial: serial::Serial::new(),
|
serial: serial::Serial::new(),
|
||||||
@ -47,13 +45,6 @@ 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: u16) {
|
||||||
/*
|
|
||||||
self.itimer += 1;
|
|
||||||
if self.itimer == 5 {
|
|
||||||
self.display_blank_interrupt();
|
|
||||||
self.itimer = 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
self.display.tick(cycles * 4);
|
self.display.tick(cycles * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,5 +162,6 @@ impl Interconnect {
|
|||||||
|
|
||||||
pub fn read_word(&self, addr: u16) -> u16 {
|
pub fn read_word(&self, addr: u16) -> u16 {
|
||||||
self.read_byte(addr) as u16 | (self.read_byte(addr + 1) as u16) << 8
|
self.read_byte(addr) as u16 | (self.read_byte(addr + 1) as u16) << 8
|
||||||
|
// (self.read_byte(addr) as u16) << 8 | (self.read_byte(addr + 1) as u16)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user