diff --git a/src/cpu.rs b/src/cpu.rs index aee7a27..fe3607f 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -26,6 +26,7 @@ pub struct CPU { interconnect: interconnect::Interconnect, interrupts_enabled: bool, + debug: bool, } fn to_u16(bytes: Box<[u8]>) -> u16 { @@ -43,6 +44,7 @@ impl CPU { sp: 0xFFFE, interconnect: interconnect, interrupts_enabled: false, // Is this correct? + debug: false, } } @@ -91,14 +93,18 @@ impl CPU { 0x10 ... 0x17 => { let reg_id = (instruction - 0x10) as usize; 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); } 0x40 ... 0x47 => { // Test 0th bit let reg_id = (instruction - 0x40) as usize; 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 { self.flags |= FLAG_Z; } else { @@ -109,7 +115,9 @@ impl CPU { // Test 1th bit let reg_id = (instruction - 0x48) as usize; 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 { self.flags |= FLAG_Z; } else { @@ -120,7 +128,9 @@ impl CPU { // Test 2th bit let reg_id = (instruction - 0x50) as usize; 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 { self.flags |= FLAG_Z; } else { @@ -131,7 +141,9 @@ impl CPU { // Test 3th bit let reg_id = (instruction - 0x58) as usize; 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 { self.flags |= FLAG_Z; } else { @@ -142,7 +154,9 @@ impl CPU { // Test 4th bit let reg_id = (instruction - 0x60) as usize; 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 { self.flags |= FLAG_Z; } else { @@ -153,7 +167,9 @@ impl CPU { // Test 5th bit let reg_id = (instruction - 0x68) as usize; 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 { self.flags |= FLAG_Z; } else { @@ -164,7 +180,9 @@ impl CPU { // Test 6th bit let reg_id = (instruction - 0x70) as usize; 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 { self.flags |= FLAG_Z; } else { @@ -175,7 +193,9 @@ impl CPU { // Test 7th bit let reg_id = (instruction - 0x78) as usize; 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 { self.flags |= FLAG_Z; } else { @@ -221,99 +241,156 @@ impl CPU { self.flags |= FLAG_N; } - pub fn run_instruction(&mut self) { - let instruction = self.read_byte(self.ip); - 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)); + fn set_flag(&mut self, flag: u8) { + self.flags |= flag; + } - // 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); + fn clear_flag(&mut self, flag: u8) { + self.flags &= !flag; + } + + 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; - let mut cycles: u16; + let cycles: u16; match instruction { 0x00 => { - println!("NOP"); + if self.debug { + println!("NOP"); + } cycles = 4; }, 0x01 => { - println!("LD (BC), A"); + 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 = 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 => { - println!("INC B"); + if self.debug{ + println!("INC B"); + } self.reg_inc(REG_B); cycles = 4; }, 0x05 => { - println!("DEC B"); + if self.debug { + println!("DEC B"); + } self.reg_dec(REG_B); cycles = 4; }, 0x06 => { 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]; cycles = 8; }, 0x0C => { - println!("INC C"); + if self.debug { + println!("INC C"); + } self.reg_inc(REG_C); cycles = 4; }, 0x0D => { - println!("DEC C"); + if self.debug { + println!("DEC C"); + } self.reg_dec(REG_C); cycles = 4; }, 0x0E => { 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]; cycles = 8; }, 0x11 => { let args = self.load_args(2); 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); 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 => { - println!("INC DE"); + if self.debug { + println!("INC DE"); + } let old_value = self.get_pair_value(REG_D, REG_E); self.set_pair_value(REG_D, REG_E, old_value + 1); cycles = 8; }, 0x14 => { - println!("INC D"); + if self.debug { + println!("INC D"); + } self.reg_inc(REG_D); cycles = 4; }, 0x15 => { - println!("DEC D"); + if self.debug { + println!("DEC D"); + } self.reg_dec(REG_D); cycles = 4; }, 0x16 => { 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]; cycles = 8; }, 0x17 => { - println!("RLA"); + if self.debug { + println!("RLA"); + } let carry = self.flags & FLAG_C == FLAG_C; if !carry { // No carry before, now we got a carry => set it @@ -331,7 +408,9 @@ impl CPU { }, 0x18 => { 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; if off < 0 { self.ip -= (-off) as u16; @@ -341,29 +420,39 @@ impl CPU { cycles = 12; }, 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)); cycles = 8; }, 0x1C => { - println!("INC E"); + if self.debug { + println!("INC E"); + } self.reg_inc(REG_E); cycles = 4; }, 0x1D => { - println!("DEC E"); + if self.debug { + println!("DEC E"); + } self.reg_dec(REG_E); cycles = 4; }, 0x1E => { 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]; cycles = 8; }, 0x20 => { 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 { let offset = args[0] as i8; if offset < 0 { @@ -378,48 +467,62 @@ impl CPU { } 0x21 => { 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); cycles = 12; }, 0x22 => { - println!("LD (HL+), A"); + if self.debug { + println!("LD (HL+), A"); + } let addr: u16 = self.get_pair_value(REG_H, REG_L); self.interconnect.write_byte(addr, self.regs[REG_A]); self.set_pair_value(REG_H, REG_L, addr + 1); cycles = 8; }, 0x23 => { - println!("INC HL"); + if self.debug { + println!("INC HL"); + } let old_value = self.get_pair_value(REG_H, REG_L); self.set_pair_value(REG_H, REG_L, old_value + 1); cycles = 8; }, 0x24 => { - println!("INC H"); + if self.debug { + println!("INC H"); + } self.reg_inc(REG_H); cycles = 4; }, 0x25 => { - println!("DEC H"); + if self.debug { + println!("DEC H"); + } self.reg_dec(REG_H); cycles = 4; }, 0x26 => { 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]; cycles = 8; }, 0x28 => { let args = self.load_args(1); - let mut target; - if args[0] < 0 { + let target; + if (args[0] as i8) < 0 { target = self.ip - (-(args[0] as i8)) as u16; } else { 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 { self.ip = target; cycles = 12; @@ -427,30 +530,48 @@ impl CPU { 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 => { - println!("INC L"); + if self.debug { + println!("INC L"); + } self.reg_inc(REG_L); cycles = 4; }, 0x2D => { - println!("DEC L"); + if self.debug { + println!("DEC L"); + } self.reg_dec(REG_L); cycles = 4; }, 0x2E => { 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]; cycles = 8; }, 0x31 => { let args = self.load_args(2); self.sp = to_u16(args); - println!("LD SP, {:02x}", self.sp); + if self.debug { + println!("LD SP, {:02x}", self.sp); + } cycles = 12; }, 0x32 => { - println!("LD (HL-), A"); + if self.debug { + println!("LD (HL-), A"); + } let mut addr = self.get_pair_value(REG_H, REG_L); self.interconnect.write_byte(addr, self.regs[REG_A]); @@ -460,24 +581,32 @@ impl CPU { }, 0x36 => { 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); self.interconnect.write_byte(addr, args[0]); cycles = 12; }, 0x3C => { - println!("INC A"); + if self.debug { + println!("INC A"); + } self.reg_inc(REG_A); cycles = 4; } 0x3D => { - println!("DEC A"); + if self.debug { + println!("DEC A"); + } self.reg_dec(REG_A); cycles = 4; } 0x3E => { 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]; cycles = 8; }, @@ -485,43 +614,57 @@ impl CPU { // LDs 0x40 ... 0x47 => { 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); cycles = 4; }, 0x48 ... 0x4F => { 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); cycles = 4; }, 0x50 ... 0x57 => { 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); cycles = 4; }, 0x58 ... 0x5F => { 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); cycles = 4; }, 0x60 ... 0x67 => { 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); cycles = 4; }, 0x68 ... 0x6F => { 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); cycles = 4; }, 0x70 ... 0x75 | 0x77 => { 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 addr: u16 = self.get_pair_value(REG_H, REG_L); cycles = 8; @@ -530,7 +673,9 @@ impl CPU { }, 0x78 ... 0x7F => { 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); cycles = 4; }, @@ -538,9 +683,12 @@ impl CPU { // ADD 0x80 ... 0x87 => { 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.flags &= !FLAG_N; + + self.clear_flag(FLAG_N); cycles = 4; } @@ -552,20 +700,23 @@ impl CPU { if self.flags & FLAG_C == FLAG_C { self.regs[REG_A] = self.regs[REG_A].wrapping_add(1); } - self.flags &= !FLAG_N; + + self.set_flag(FLAG_N); cycles = 4; } // SUBs 0x90 ... 0x97 => { 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.flags |= FLAG_N; + self.set_flag(FLAG_N); if self.regs[REG_A] == 0 { - self.flags |= FLAG_Z; + self.set_flag(FLAG_Z); } else { - self.flags &= !FLAG_Z; + self.clear_flag(FLAG_Z); } // TODO: H, C cycles = 4; @@ -574,50 +725,66 @@ impl CPU { // SBC 0x98 ... 0x9F => { 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)); if self.flags & FLAG_C == FLAG_C { 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; } // XOR 0xA8 ... 0xAF => { 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); if self.regs[REG_A] == 0 { - self.flags |= FLAG_Z; + self.set_flag(FLAG_Z); } else { - self.flags &= !FLAG_Z; + self.set_flag(FLAG_Z); } - self.flags &= !FLAG_C; - self.flags &= !FLAG_N; - self.flags &= !FLAG_H; + + self.clear_flag(FLAG_C); + self.clear_flag(FLAG_N); + self.clear_flag(FLAG_H); cycles = 4; }, // CP 0xB8 ... 0xBF => { 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); - if self.regs[REG_A] < self.get_8bit_reg(reg_id) { - self.flags |= FLAG_C; - self.flags &= !FLAG_Z; - } else if self.regs[REG_A] == self.get_8bit_reg(reg_id) { - self.flags |= FLAG_Z; - self.flags &= !FLAG_C; + + self.set_flag(FLAG_N); + if self.regs[REG_A] < val { + self.set_flag(FLAG_C); + self.clear_flag(FLAG_Z); + } else if self.regs[REG_A] == val { + self.clear_flag(FLAG_C); + self.set_flag(FLAG_Z); } else { - self.flags &= !FLAG_Z; - self.flags &= !FLAG_C; + self.clear_flag(FLAG_C); + self.clear_flag(FLAG_Z); } cycles = 4; }, 0xC1 => { - println!("POP BC"); + if self.debug { + println!("POP BC"); + } let val: u16 = self.interconnect.read_word(self.sp); self.sp += 2; self.set_pair_value(REG_B, REG_C, val); @@ -625,7 +792,9 @@ impl CPU { }, 0xC2 => { 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 { self.ip = addr; cycles = 16; @@ -635,13 +804,17 @@ impl CPU { }, 0xC3 => { let addr: u16 = to_u16(self.load_args(2)); - println!("JP {:04X}", addr); + if self.debug { + println!("JP {:04X}", addr); + } self.ip = addr; cycles = 16; } 0xC4 => { 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 { // Push current IP to the stack self.interconnect.write_word(self.sp - 1, self.ip); @@ -653,14 +826,18 @@ impl CPU { } }, 0xC5 => { - println!("PUSH BC"); + 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 => { - println!("RET"); + if self.debug { + println!("RET"); + } self.dump_stack(); self.ip = self.interconnect.read_word(self.sp+1); self.sp += 2; @@ -673,7 +850,9 @@ impl CPU { }, 0xCC => { 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 { // Push current IP to the stack self.interconnect.write_word(self.sp - 1, self.ip); @@ -686,7 +865,9 @@ impl CPU { }, 0xCD => { 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 self.interconnect.write_word(self.sp - 1, self.ip); self.sp -= 2; @@ -695,60 +876,74 @@ impl CPU { }, 0xE0 => { 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]); cycles = 12; }, 0xE2 => { - println!("LD (C), A"); - println!("[{:04X}] = {:02X}", 0xFF00 + self.regs[REG_C] as u16, self.regs[REG_A]); + if self.debug { + 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]); cycles = 8; }, 0xEA => { 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]); cycles = 16; } 0xF0 => { 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); cycles = 12; }, 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); cycles = 8; }, 0xF3 => { - println!("DI"); + if self.debug { + println!("DI"); + } self.interrupts_enabled = false; cycles = 4; } 0xFB => { // Enable interrupts - TODO - println!("EI"); + if self.debug { + println!("EI"); + } self.interrupts_enabled = true; - // self.interconnect.write_byte(0xFFFF, 0x01); - // panic!("Uh uh"); cycles = 4; panic!("ENABLING INTERRUPTS - TODO"); }, 0xFE => { let args = self.load_args(1); - println!("CP {:02X}", args[0]); - self.flags |= FLAG_N; + if self.debug { + println!("CP {:02X}", args[0]); + } + self.set_flag(FLAG_N); if args[0] > self.regs[REG_A] { - self.flags |= FLAG_C; + self.set_flag(FLAG_C); } else { - self.flags &= !FLAG_C; + self.clear_flag(FLAG_C); } if args[0] == self.regs[REG_A] { - self.flags |= FLAG_Z; + self.set_flag(FLAG_Z); } else { - self.flags &= !FLAG_Z; + self.clear_flag(FLAG_Z); } // TODO H diff --git a/src/display.rs b/src/display.rs index a793bd5..e315b74 100644 --- a/src/display.rs +++ b/src/display.rs @@ -15,6 +15,16 @@ const GB_PIXELS_X: u16 = 160; const GB_PIXELS_Y: u16 = 144; 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)] enum DisplayMode { Scanline, @@ -171,7 +181,7 @@ impl Display { // Points to the background map offset to use. let background_map: usize; // verify! - if self.control & (1 << 3) > 0 { + if self.control & CTRL_BG_TILE_MAP_SELECT > 0 { background_map = 0x1C00; } else { background_map = 0x1800; @@ -183,13 +193,13 @@ impl Display { let render_y: u8 = self.curline; - if self.control & (1 << 1) > 0 { - panic!("Switch OBJ not supported"); + if self.control & CTRL_BG_SPRITE_ENABLE > 0 { + panic!("Sprites not supported"); } // Render background - if self.control & (1 << 0) > 0 { - println!("Render background"); + if self.control & CTRL_BG_DISPLAY > 0 { + print!("Drawing tiles: "); // Render pixels (20 tiles) for render_x in 0 .. 160 { // Absolute render coordinates @@ -203,37 +213,24 @@ impl Display { 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; + // 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]; - /* - 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); + // println!("vram offset: {:04X}", vram_offset); if tile_id != 0 { - println!("Drawing tile {:02X}", tile_id); + // println!("Drawing tile {:02X}", tile_id); + print!("{:02X} ", tile_id); } // Obtain tile information 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; } else { tile_base_addr = 0x0800; // This set goes from -127 to 127. let s_tid: i8 = tile_id as i8; - if s_tid < 0 { - tile_id = (127 + s_tid) as u8; - } else { - tile_id = tile_id + 127; - } + tile_id = (128 + s_tid) as u8; panic!("OH MY GOD, this wasn't tested yet"); } @@ -253,14 +250,11 @@ impl Display { 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(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) { diff --git a/src/interconnect.rs b/src/interconnect.rs index 33aaff6..992bf0c 100644 --- a/src/interconnect.rs +++ b/src/interconnect.rs @@ -18,7 +18,6 @@ pub struct Interconnect { display: display::Display, interrupt: u8, iflags: u8, - itimer: u8, disable_bootrom: u8, infrared_com_port: u8, serial: serial::Serial, @@ -38,7 +37,6 @@ impl Interconnect { iflags: 0, interrupt: 0, infrared_com_port: 0, - itimer: 0, disable_bootrom: 0, timer: timer::Timer::new(), serial: serial::Serial::new(), @@ -47,13 +45,6 @@ impl Interconnect { // Somehow we need different timers for this. 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); } @@ -171,5 +162,6 @@ impl Interconnect { 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) << 8 | (self.read_byte(addr + 1) as u16) } }