<commit_before>use super::bus::{Bus, Addressable};
use super::byteorder::{ByteOrder, LittleEndian};
use super::registers::*;

enum Condition {
    None,
    Z,
    C,
    Nz,
    Nc
}

pub struct Cpu {
    regs: Registers,
    bus: Bus
}

impl Cpu {
    pub fn new(bus: Bus) -> Cpu {
        Cpu {
            regs: Registers::default(),
            bus: bus
        }
    }

    pub fn power_on(&mut self) {
        self.regs.a = 0x01;
        self.regs.b = 0x13;
        self.regs.c = 0x00;
        self.regs.d = 0xD8;
        self.regs.e = 0x00;
        self.regs.flags = 0xB0;
        self.regs.h = 0x4D;
        self.regs.l = 0x01;
        self.regs.sp = 0xFFFE;
        self.regs.pc = 0x100;
    }

    pub fn step(&mut self) -> usize {
        let opcode = self.inc_imm_byte();
        self.execute(opcode)
    }

    fn inc_imm_byte(&mut self) -> u8 {
        let byte = self.bus.read(self.regs.pc);
        self.regs.pc = self.regs.pc + 1;

        byte
    }

    fn inc_imm_word(&mut self) -> u16 {
        let word = &[self.bus.read(self.regs.pc), self.bus.read(self.regs.pc+1)];
        self.regs.pc = self.regs.pc + 2;

        LittleEndian::read_u16(word)
    }

    fn execute(&mut self, opcode: u8) -> usize {
        use super::registers::Register8::*;
        use super::registers::Register16::*;

        match opcode {
            0x00 => { self.nop(); 4 },
            0x01 => { self.ld_rr_d16(BC); 12 },
            0x02 => { self.ld_indrr_a(BC); 8 },
            0x03 => { self.inc_rr(BC); 8 },
            0x04 => { self.inc_r(B); 4 },
            0x05 => { self.dec_r(B); 4 },
            0x06 => { self.ld_r_d8(B); 8 },
            0x07 => { self.rlca(); 4 },
            0x08 => { self.ld_a16_sp(); 20 },
            0x09 => { self.add_rr_rr(HL, BC); 8 },
            0x0A => { self.ld_a_indrr(BC); 8 },
            0x0B => { self.dec_rr(BC); 8 },
            0x0C => { self.inc_r(C); 4 },
            0x0D => { self.dec_r(C); 4 },
            0x0E => { self.ld_r_d8(C); 8 },
            0x0F => { self.rrca(); 4 },

            0x10 => { self.stop(); 4 },
            0x11 => { self.ld_rr_d16(DE); 12 },
            0x12 => { self.ld_indrr_a(DE); 8 },
            0x13 => { self.inc_rr(DE); 8 },
            0x14 => { self.inc_r(D); 4 },
            0x15 => { self.dec_r(D); 4 },
            0x16 => { self.ld_r_d8(D); 8 },
            0x17 => { self.rla(); 4 },
            0x18 => { self.jr(Condition::None); 12 },
            0x19 => { self.add_rr_rr(HL, DE); 8 },
            0x1A => { self.ld_a_indrr(DE); 8 },
            0x1B => { self.dec_rr(DE); 8 },
            0x1C => { self.inc_r(E); 4 },
            0x1D => { self.dec_r(E); 4 },
            0x1E => { self.ld_r_d8(E); 8 },
            0x1F => { self.rra(); 4 },

            _ => panic!("Unknown opcode: {:#X}", opcode)
        }
    }

    fn condition_met(&self, cond: Condition) -> bool {
        match cond {
            Condition::None => true,
            Condition::C => self.regs.is_flag_set(Flag::C),
            Condition::Z => self.regs.is_flag_set(Flag::Z),
            Condition::Nc => !self.regs.is_flag_set(Flag::C),
            Condition::Nz => !self.regs.is_flag_set(Flag::Z)
        }
    }

    /*
     * 8-bit load instructions
     */

    // LD r, d8
    #[inline(always)]
    fn ld_r_d8(&mut self, dest: Register8) {
        let val = self.inc_imm_byte();
        self.regs.write_u8(&dest, val);
    }

    // LD r, r
    #[inline(always)]
    fn ld_r_r(&mut self, dest: Register8, src: Register8) {
        let val = self.regs.read_u8(&src);
        self.regs.write_u8(&dest, val);
    }

    // LD (rr), A
    #[inline(always)]
    fn ld_indrr_a(&mut self, dest: Register16) {
        let addr = self.regs.read_u16(&dest);
        let val = self.regs.a;
        self.bus.write(addr, val);
    }

    // LD A, (rr)
    #[inline(always)]
    fn ld_a_indrr(&mut self, src: Register16) {
        let addr = self.regs.read_u16(&src);
        let val = self.bus.read(addr);
        self.regs.a = val;
    }

    /*
     * 8-bit math instructions
     */

    // INC r
    // Affects flags: Z, N, H
    #[inline(always)]
    fn inc_r(&mut self, reg: Register8) {
        let val = self.regs.read_u8(&reg);
        let increased = val.wrapping_add(1);

        self.regs.write_u8(&reg, increased);

        self.regs.flags =
            (if increased == 0 { 1 << 7 } else { 0 })   // Z
            | (((val & 0xF) + 1) & 0b00010000) << 1     // H
            | self.regs.flags & (Flag::C as u8)         // C

    }

    // DEC r
    // Affects flags: Z, N, H
    #[inline(always)]
    fn dec_r(&mut self, reg: Register8) {
        let val = self.regs.read_u8(&reg);
        let decreased = val.wrapping_sub(1);

        self.regs.write_u8(&reg, decreased);

        self.regs.flags =
            (if decreased == 0 { 1 << 7 } else { 0 })                   // Z
            | Flag::N as u8                                             // N
            | if (((val & 0xF0) - 1) & 0b00001000) == 0b00001000        // H
                { 1 << 6 }
                else { 0 }
            | self.regs.flags & (Flag::C as u8)                         // C
    }

    /*
     * 8-bit bit instructions
     */

    // RLCA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rlca(&mut self) {
        let val = self.regs.a;
        let adj = val << 1;
        let carry = (val >> 7) & 0b00000001;

        self.regs.a = adj | carry;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | carry << 4          // C
    }

    // RLA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rla(&mut self) {
        let val = self.regs.a;
        let adj = (val << 1) | ((self.regs.flags & Flag::C as u8) >> 4);

        self.regs.a = adj;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | (val & 0b10000000) >> 3           // C
    }

    // RRCA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rrca(&mut self) {
        let val = self.regs.a;
        let adj = val >> 1;
        let carry = val & 0b00000001;

        self.regs.a = adj | (carry << 7);

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | carry << 4                        // C
    }

    // RRA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rra(&mut self) {
        let val = self.regs.a;
        let adj = (val >> 1) | ((self.regs.flags & Flag::C as u8) << 3);

        self.regs.a = adj;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | adj << 4                          // C
    }

    /*
     * 16-bit load instructions
     */

     // LD rr, d16
    #[inline(always)]
    fn ld_rr_d16(&mut self, dest: Register16) {
        let val = self.inc_imm_word();
        self.regs.write_u16(&dest, val);
    }

    // LD (a16), SP
    #[inline(always)]
    fn ld_a16_sp(&mut self) {
        let addr = self.inc_imm_word();
        self.bus.write(addr, (self.regs.sp & 0x00FF) as u8);
        self.bus.write(addr + 1, (self.regs.sp >> 8) as u8);
    }

    /*
     * 16-bit math instructions
     */

    // INC rr
    #[inline(always)]
    fn inc_rr(&mut self, reg: Register16) {
        let val = self.regs.read_u16(&reg);
        self.regs.write_u16(&reg, val.wrapping_add(1));
    }

    // DEC rr
    #[inline(always)]
    fn dec_rr(&mut self, reg: Register16) {
        let val = self.regs.read_u16(&reg);
        self.regs.write_u16(&reg, val.wrapping_sub(1));
    }

    // ADD rr, rr
    // Affects flags: N, H, C
    #[inline(always)]
    fn add_rr_rr(&mut self, dest: Register16, src: Register16) {
        let src_val = self.regs.read_u16(&src);
        let dest_val = self.regs.read_u16(&dest);

        self.regs.write_u16(&dest, dest_val.wrapping_add(src_val));

        let src_high = ((src_val & 0xF0) >> 8) as u8;
        let dest_high = ((dest_val & 0xF0) >> 8) as u8;

        self.regs.flags =
            (self.regs.flags & Flag::Z as u8) // Z
            | (((dest_high & 0xF) + (src_high & 0xF)) & 0b00010000) << 1    // H
            | if dest_val.wrapping_add(src_val) < src_val                   // C
                { Flag::C as u8 }
                else { 0 };
    }

    // JR c, r8
    #[inline(always)]
    fn jr(&mut self, condition: Condition) {
        let pc = self.regs.pc;
        let offset = self.inc_imm_byte() as i16;

        if (offset > 0) {
            self.regs.pc = pc.wrapping_add(offset as u16);
        } else {
            self.regs.pc = pc.wrapping_sub(offset.abs() as u16);
        }
    }

    /*
     * Misc instructions
     */

     // NOP
    #[inline(always)]
    fn nop(&self) {
        // Ahh, doing nothing feels so good!
    }

    // STOP 0
    // TODO: halt cpu/lcd
    #[inline(always)]
    fn stop(&mut self) {
        // This instruction is 2 bytes.
        self.inc_imm_byte();
    }
}<commit_msg>Added another set of instructions<commit_after>use super::bus::{Bus, Addressable};
use super::byteorder::{ByteOrder, LittleEndian};
use super::registers::*;

enum Condition {
    None,
    Z,
    C,
    Nz,
    Nc
}

pub struct Cpu {
    regs: Registers,
    bus: Bus
}

impl Cpu {
    pub fn new(bus: Bus) -> Cpu {
        Cpu {
            regs: Registers::default(),
            bus: bus
        }
    }

    pub fn power_on(&mut self) {
        self.regs.a = 0x01;
        self.regs.b = 0x13;
        self.regs.c = 0x00;
        self.regs.d = 0xD8;
        self.regs.e = 0x00;
        self.regs.flags = 0xB0;
        self.regs.h = 0x4D;
        self.regs.l = 0x01;
        self.regs.sp = 0xFFFE;
        self.regs.pc = 0x100;
    }

    pub fn step(&mut self) -> usize {
        let opcode = self.inc_imm_byte();
        self.execute(opcode)
    }

    fn inc_imm_byte(&mut self) -> u8 {
        let byte = self.bus.read(self.regs.pc);
        self.regs.pc = self.regs.pc + 1;

        byte
    }

    fn inc_imm_word(&mut self) -> u16 {
        let word = &[self.bus.read(self.regs.pc), self.bus.read(self.regs.pc+1)];
        self.regs.pc = self.regs.pc + 2;

        LittleEndian::read_u16(word)
    }

    fn execute(&mut self, opcode: u8) -> usize {
        use super::registers::Register8::*;
        use super::registers::Register16::*;

        match opcode {
            0x00 => { self.nop(); 4 },
            0x01 => { self.ld_rr_d16(BC); 12 },
            0x02 => { self.ld_indrr_a(BC); 8 },
            0x03 => { self.inc_rr(BC); 8 },
            0x04 => { self.inc_r(B); 4 },
            0x05 => { self.dec_r(B); 4 },
            0x06 => { self.ld_r_d8(B); 8 },
            0x07 => { self.rlca(); 4 },
            0x08 => { self.ld_a16_sp(); 20 },
            0x09 => { self.add_rr_rr(HL, BC); 8 },
            0x0A => { self.ld_a_indrr(BC); 8 },
            0x0B => { self.dec_rr(BC); 8 },
            0x0C => { self.inc_r(C); 4 },
            0x0D => { self.dec_r(C); 4 },
            0x0E => { self.ld_r_d8(C); 8 },
            0x0F => { self.rrca(); 4 },

            0x10 => { self.stop(); 4 },
            0x11 => { self.ld_rr_d16(DE); 12 },
            0x12 => { self.ld_indrr_a(DE); 8 },
            0x13 => { self.inc_rr(DE); 8 },
            0x14 => { self.inc_r(D); 4 },
            0x15 => { self.dec_r(D); 4 },
            0x16 => { self.ld_r_d8(D); 8 },
            0x17 => { self.rla(); 4 },
            0x18 => { self.jr(Condition::None); 12 },
            0x19 => { self.add_rr_rr(HL, DE); 8 },
            0x1A => { self.ld_a_indrr(DE); 8 },
            0x1B => { self.dec_rr(DE); 8 },
            0x1C => { self.inc_r(E); 4 },
            0x1D => { self.dec_r(E); 4 },
            0x1E => { self.ld_r_d8(E); 8 },
            0x1F => { self.rra(); 4 },

            0x20 => self.jr(Condition::Nz),
            0x21 => { self.ld_rr_d16(HL); 12 },
            0x22 => { self.ldi_hl_a(); 8 },
            0x23 => { self.inc_rr(HL); 8 },
            0x24 => { self.inc_r(H); 4 },
            0x25 => { self.dec_r(H); 4 },
            0x26 => { self.ld_r_d8(H); 8 },
            0x27 => { self.daa(); 4 },
            0x28 => { self.jr(Condition::Z) },
            0x29 => { self.add_rr_rr(HL, HL); 8 },
            0x2A => { self.ldi_a_hl(); 8 },
            0x2B => { self.dec_rr(HL); 8 },
            0x2C => { self.inc_r(L); 4 },
            0x2D => { self.dec_r(L); 4 },
            0x2E => { self.ld_r_d8(L); 8 },
            0x2F => { self.cpl(); 4 },

            _ => panic!("Unknown opcode: {:#X}", opcode)
        }
    }

    fn condition_met(&self, cond: Condition) -> bool {
        match cond {
            Condition::None => true,
            Condition::C => self.regs.is_flag_set(Flag::C),
            Condition::Z => self.regs.is_flag_set(Flag::Z),
            Condition::Nc => !self.regs.is_flag_set(Flag::C),
            Condition::Nz => !self.regs.is_flag_set(Flag::Z)
        }
    }

    /*
     * 8-bit load instructions
     */

    // LD r, d8
    #[inline(always)]
    fn ld_r_d8(&mut self, dest: Register8) {
        let val = self.inc_imm_byte();
        self.regs.write_u8(&dest, val);
    }

    // LD r, r
    #[inline(always)]
    fn ld_r_r(&mut self, dest: Register8, src: Register8) {
        let val = self.regs.read_u8(&src);
        self.regs.write_u8(&dest, val);
    }

    // LD (rr), A
    #[inline(always)]
    fn ld_indrr_a(&mut self, dest: Register16) {
        let addr = self.regs.read_u16(&dest);
        let val = self.regs.a;
        self.bus.write(addr, val);
    }

    // LD A, (rr)
    #[inline(always)]
    fn ld_a_indrr(&mut self, src: Register16) {
        let addr = self.regs.read_u16(&src);
        let val = self.bus.read(addr);
        self.regs.a = val;
    }

    // LD (HL+), A
    #[inline(always)]
    fn ldi_hl_a(&mut self) {
        let addr = self.regs.read_u16(&Register16::HL);

        self.bus.write(addr, self.regs.a);
        self.regs.write_u16(&Register16::HL, addr.wrapping_add(1));
    }

    // LD A, (HL+)
    #[inline(always)]
    fn ldi_a_hl(&mut self) {
        let addr = self.regs.read_u16(&Register16::HL);

        self.regs.a = self.bus.read(addr);
        self.regs.write_u16(&Register16::HL, addr.wrapping_add(1));
    }

    /*
     * 8-bit math instructions
     */

    // INC r
    // Affects flags: Z, N, H
    #[inline(always)]
    fn inc_r(&mut self, reg: Register8) {
        let val = self.regs.read_u8(&reg);
        let increased = val.wrapping_add(1);

        self.regs.write_u8(&reg, increased);

        self.regs.flags =
            (if increased == 0 { 1 << 7 } else { 0 })   // Z
            | (((val & 0xF) + 1) & 0b00010000) << 1     // H
            | self.regs.flags & (Flag::C as u8)         // C

    }

    // DEC r
    // Affects flags: Z, N, H
    #[inline(always)]
    fn dec_r(&mut self, reg: Register8) {
        let val = self.regs.read_u8(&reg);
        let decreased = val.wrapping_sub(1);

        self.regs.write_u8(&reg, decreased);

        self.regs.flags =
            (if decreased == 0 { 1 << 7 } else { 0 })                   // Z
            | Flag::N as u8                                             // N
            | if (((val & 0xF0) - 1) & 0b00001000) == 0b00001000        // H
                { 1 << 6 }
                else { 0 }
            | self.regs.flags & (Flag::C as u8)                         // C
    }

    // CPL
    // Flags affected: N, H
    #[inline(always)]
    fn cpl(&mut self) {
        self.regs.a = !self.regs.a;

        self.regs.flags =
            self.regs.flags
            | (Flag::N as u8)
            | (Flag::H as u8)
    }

    /*
     * 8-bit bit instructions
     */

    // RLCA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rlca(&mut self) {
        let val = self.regs.a;
        let adj = val << 1;
        let carry = (val >> 7) & 0b00000001;

        self.regs.a = adj | carry;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | carry << 4          // C
    }

    // RLA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rla(&mut self) {
        let val = self.regs.a;
        let adj = (val << 1) | ((self.regs.flags & Flag::C as u8) >> 4);

        self.regs.a = adj;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | (val & 0b10000000) >> 3           // C
    }

    // RRCA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rrca(&mut self) {
        let val = self.regs.a;
        let adj = val >> 1;
        let carry = val & 0b00000001;

        self.regs.a = adj | (carry << 7);

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | carry << 4                        // C
    }

    // RRA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rra(&mut self) {
        let val = self.regs.a;
        let adj = (val >> 1) | ((self.regs.flags & Flag::C as u8) << 3);

        self.regs.a = adj;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | adj << 4                          // C
    }

    // DAA
    // Flags affected: Z, H, C
    #[inline(always)]
    fn daa (&mut self) {
        // TODO
    }

    /*
     * 16-bit load instructions
     */

     // LD rr, d16
    #[inline(always)]
    fn ld_rr_d16(&mut self, dest: Register16) {
        let val = self.inc_imm_word();
        self.regs.write_u16(&dest, val);
    }

    // LD (a16), SP
    #[inline(always)]
    fn ld_a16_sp(&mut self) {
        let addr = self.inc_imm_word();
        self.bus.write(addr, (self.regs.sp & 0x00FF) as u8);
        self.bus.write(addr + 1, (self.regs.sp >> 8) as u8);
    }

    /*
     * 16-bit math instructions
     */

    // INC rr
    #[inline(always)]
    fn inc_rr(&mut self, reg: Register16) {
        let val = self.regs.read_u16(&reg);
        self.regs.write_u16(&reg, val.wrapping_add(1));
    }

    // DEC rr
    #[inline(always)]
    fn dec_rr(&mut self, reg: Register16) {
        let val = self.regs.read_u16(&reg);
        self.regs.write_u16(&reg, val.wrapping_sub(1));
    }

    // ADD rr, rr
    // Affects flags: N, H, C
    #[inline(always)]
    fn add_rr_rr(&mut self, dest: Register16, src: Register16) {
        let src_val = self.regs.read_u16(&src);
        let dest_val = self.regs.read_u16(&dest);

        self.regs.write_u16(&dest, dest_val.wrapping_add(src_val));

        let src_high = ((src_val & 0xF0) >> 8) as u8;
        let dest_high = ((dest_val & 0xF0) >> 8) as u8;

        self.regs.flags =
            (self.regs.flags & Flag::Z as u8) // Z
            | (((dest_high & 0xF) + (src_high & 0xF)) & 0b00010000) << 1    // H
            | if dest_val.wrapping_add(src_val) < src_val                   // C
                { Flag::C as u8 }
                else { 0 };
    }

    // JR c, r8
    #[inline(always)]
    fn jr(&mut self, condition: Condition) -> usize {
        let mut cycles = 8;

        if self.condition_met(condition) {
            cycles = 12;
            let pc = self.regs.pc;
            let offset = self.inc_imm_byte() as i16;

            if offset > 0 {
                self.regs.pc = pc.wrapping_add(offset as u16);
            } else {
                self.regs.pc = pc.wrapping_sub(offset.abs() as u16);
            }
        }

        cycles
    }

    /*
     * Misc instructions
     */

     // NOP
    #[inline(always)]
    fn nop(&self) {
        // Ahh, doing nothing feels so good!
    }

    // STOP 0
    // TODO: halt cpu/lcd
    #[inline(always)]
    fn stop(&mut self) {
        // This instruction is 2 bytes.
        self.inc_imm_byte();
    }
}<|endoftext|>


<commit_before>use std::thread::sleep;
use std::time::Duration;
use super::interconnect::Interconnect;
use super::interconnect::END_RESERVED;

const INSTRUCTION_SIZE: u16 = 2;
const TIMER_DELAY: u64 = 16;

#[derive(Default, Debug)]
pub struct Cpu {
    // Interconnect is used to control system resources like rom and memory.
    interconnect: Interconnect,

    // Program counter.
    pc: u16,

    // The function call stack.
    stack: [u16; 16],

    // Stack pointer.
    sp: u8,

    // General purpose registers v0-vf.
    v0: u8,
    v1: u8,
    v2: u8,
    v3: u8,
    v4: u8,
    v5: u8,
    v6: u8,
    v7: u8,
    v8: u8,
    v9: u8,
    va: u8,
    vb: u8,
    vc: u8,
    vd: u8,
    ve: u8,
    vf: u8,

    // Address register "I".
    i: u16,

    // Timer and sound registers.
    dt: u8,
    st: u8,
}

impl Cpu {
    pub fn new(interconnect: Interconnect) -> Cpu {
        Cpu {
            interconnect: interconnect,
            pc: END_RESERVED as u16,
            ..Cpu::default()
        }
    }

    /// Execute instructions from ram.
    pub fn run(&mut self) {
        loop {
            let word = self.interconnect.read_word(self.pc);

            // Execute until the subroutine ends.
            if self.execute_instruction(word) {
                break
            }
        }
    }

    #[inline(always)]
    fn execute_instruction(&mut self, instr: u16) -> bool {
        let opcode = (instr >> 12) as u8;
        let mut ret: bool = false;

        match opcode {
            0x0 => {
                let identifier = ((instr << 8) >> 8) as u8;

                match identifier {
                    0xE0 => {
                        // 00E0 - CLS
                        // Clears the screen.

                        self.interconnect.clear_display();
                    },
                    0xEE => {
                        // 00EE - RET
                        // Returns from a subroutine.

                        self.sp -= 1;
                        self.pc = self.stack[self.sp as usize];
                        self.stack[self.sp as usize] = 0;

                        // Break out of the execution loop for the current
                        // subroutine.
                        ret = true;
                    },
                    _ => {
                        println!("cpu: {:#?}", self);
                        panic!("Found unknown identifier at instruction: {:#x}, addr: {:#x}", instr, self.pc);
                    },
                }
            },
            0x1 => {
                // 1NNN - JP NNN
                //
                // Jumps to address NNN.

                let addr = ((instr << 4) >> 4) as u16;
                self.pc = addr;
            },
            0x2 => {
                // 2NNN - CALL NNN
                //
                // Calls subroutine at NNN.

                let addr = ((instr << 4) >> 4) as u16;

                // Add the current program counter to the call stack.
                self.stack[self.sp as usize] = self.pc;
                self.sp += 1;

                // Set the program counter to the call address begin executing
                // the subroutine.
                self.pc = addr;
                self.run();
            },
            0x3 => {
                // 3XNN - SE VX, NN
                //
                // Skips the next instruction if VX equals NN.

                let regx = ((instr << 4) >> 12) as u8;
                let byte = ((instr << 8) >> 8) as u8;
                let x = self.get_reg(regx);

                if x == byte {
                    self.pc += 2;
                }
            }
            0x6 => {
                // 6XNN - LD VX, NN
                //
                // Sets VX to NN.

                let regx = ((instr << 4) >> 12) as u8;
                let byte = ((instr << 8) >> 8) as u8;
                self.set_reg(regx, byte);
            },
            0x7 => {
                // 7XNN - ADD VX, NN
                //
                // Adds NN to VX.

                let regx = ((instr << 4) >> 12) as u8;
                let byte = ((instr << 8) >> 8) as u8;

                let result = self.get_reg(regx) + byte;
                self.set_reg(regx, result);
            },
            0xa => {
                // ANNN - LD I, NNN
                //
                // Sets I to the address NNN.

                let addr = ((instr << 4) >> 4) as u16;
                self.i = addr;
            },
            0xd => {
                // DXYN - DRW VX, VY, N
                //
                // Sprites stored in memory at location in index register (I),
                // 8bits wide. Wraps around the screen. If when drawn, clears a
                // pixel, register VF is set to 1 otherwise it is zero.
                //
                // All drawing is XOR drawing (i.e. it toggles the screen
                // pixels). Sprites are drawn starting at position VX, VY. N is
                // the number of 8bit rows that need to be drawn. If N is
                // greater than 1, second line continues at position VX, VY+1,
                // and so on.

                let regx = ((instr << 4) >> 12) as u8;
                let regy = ((instr << 8) >> 12) as u8;
                let nibble = ((instr << 12) >> 12) as usize;

                // Read N (nibble) bytes out out of memory starting at address
                // register I into our sprite.
                let mut sprite = vec![0 as u8; nibble];
                for i in 0..nibble {
                    sprite[i] = self.interconnect.ram[self.i as usize + i];
                }

                // Get screen coordinates from the requested registers.
                let x = self.get_reg(regx);
                let y = self.get_reg(regy);

                // Draw the sprite and store collision detection results in vf.
                self.vf = self.interconnect.draw(x as usize, y as usize, sprite);
            },
            0xf => {
                let regx = ((instr << 4) >> 12) as u8;
                let identifier = ((instr << 8) >> 8) as u8;

                match identifier {
                    0x07 => {
                        // FX07 - LD VX, DT
                        //
                        // Sets VX to the value of the delay timer.

                        let dt = self.dt;
                        self.set_reg(regx, dt);
                        println!("cpu: {:#?}", self);
                    },
                    0x15 => {
                        // FX15 - LD DT, VX
                        //
                        // Sets the delay timer to VX.

                        let x: u8 = self.get_reg(regx);
                        self.dt = x;
                    },
                    0x29 => {
                        // FX29 - LD F, VX
                        //
                        // Sets I to the location of the sprite for the
                        // character in VX. Characters 0-F (in hexadecimal) are
                        // represented by a 4x5 font.

                        let x: u8 = self.get_reg(regx);
                        self.i = self.interconnect.get_font(x);
                    },
                    0x33 => {
                        // FX33 - LD B, VX
                        //
                        // Stores the Binary-coded decimal representation of VX,
                        // with the most significant of three digits at the
                        // address in I, the middle digit at I plus 1, and the
                        // least significant digit at I plus 2. (In other words,
                        // take the decimal representation of VX, place the
                        // hundreds digit in memory at location in I, the tens
                        // digit at location I+1, and the ones digit at
                        // location I+2.)

                        const DECIMAL_LENGTH: usize = 3;

                        let mut x: u8 = self.get_reg(regx);
                        let mut digits = vec![0 as u8; DECIMAL_LENGTH];
                        let mut digit_count: usize = 0;

                        // Organize the digits in the decimal into a slice.
                        while x > 0 {
                            digit_count += 1;
                            digits[DECIMAL_LENGTH - digit_count] = x % 10;
                            x /= 10;
                        }

                        // Set I, I+1, and I+3 to the values of the digits.
                        let i: usize = self.i as usize;
                        self.interconnect.ram[i] = digits[0];
                        self.interconnect.ram[i + 1] = digits[1];
                        self.interconnect.ram[i + 2] = digits[2];
                    },
                    0x65 => {
                        // FX65 - LD VX, [I]
                        //
                        // Fills V0 to VX with values from memory starting at
                        // address I.

                        let i: usize = self.i as usize;
                        let end_reg = (regx + 1) as usize;

                        for register in 0x0..end_reg {
                            let mem = self.interconnect.ram[i + register];
                            self.set_reg(register as u8, mem);
                        }
                    },
                    _ => {
                        println!("cpu: {:#?}", self);
                        panic!("Found unknown identifier at instruction: {:#x}, addr: {:#x}", instr, self.pc);
                    },
                }
            },
            _ => {
                println!("cpu: {:#?}", self);
                panic!("Found unknown opcode at instruction: {:#x}, addr: {:#x}", instr, self.pc);
            },
        }

        // Increment the program counter to the next instruction.
        if !ret {
            self.pc += INSTRUCTION_SIZE;
        }

        self.handle_timers();

        // By default the execution loop in not broken. True will be returned
        // only by a successful RET instruction is executed.
        ret
    }

    /// Handle the delay timer and play sounds.
    fn handle_timers(&mut self) {
        let dt_enabled = self.dt > 0;
        let st_enabled = self.st > 0;

        if dt_enabled || st_enabled {
            println!("SLEEPY TIME: {:x}", self.dt);
            sleep(Duration::from_millis(TIMER_DELAY));

            if dt_enabled {
                self.dt -= 1;
            }
            if st_enabled {
                self.st -= 1;
            }
        }
    }

    /// Gets the value at a specified register.
    fn get_reg(&mut self, reg: u8) -> u8 {
        match reg {
            0x0 => self.v0,
            0x1 => self.v1,
            0x2 => self.v2,
            0x3 => self.v3,
            0x4 => self.v4,
            0x5 => self.v5,
            0x6 => self.v6,
            0x7 => self.v7,
            0x8 => self.v8,
            0x9 => self.v9,
            0xa => self.va,
            0xb => self.vb,
            0xc => self.vc,
            0xd => self.vd,
            0xe => self.ve,
            0xf => self.vf,
            _ => {
                panic!("Cannot get unknown register: V{:X}", reg);
            }
        }
    }

    /// Sets the value of a general purpose register.
    fn set_reg(&mut self, reg: u8, byte: u8) {
        match reg {
            0x0 => self.v0 = byte,
            0x1 => self.v1 = byte,
            0x2 => self.v2 = byte,
            0x3 => self.v3 = byte,
            0x4 => self.v4 = byte,
            0x5 => self.v5 = byte,
            0x6 => self.v6 = byte,
            0x7 => self.v7 = byte,
            0x8 => self.v8 = byte,
            0x9 => self.v9 = byte,
            0xa => self.va = byte,
            0xb => self.vb = byte,
            0xc => self.vc = byte,
            0xd => self.vd = byte,
            0xe => self.ve = byte,
            0xf => self.vf = byte,
            _ => {
                panic!("Cannot set unknown register: V{:X}", reg);
            }
        }
    }
}
<commit_msg>Fixed JP jumping to the wrong address<commit_after>use std::thread::sleep;
use std::time::Duration;
use super::interconnect::Interconnect;
use super::interconnect::END_RESERVED;

const INSTRUCTION_SIZE: u16 = 2;
const TIMER_DELAY: u64 = 16;

#[derive(Default, Debug)]
pub struct Cpu {
    // Interconnect is used to control system resources like rom and memory.
    interconnect: Interconnect,

    // Program counter.
    pc: u16,

    // The function call stack.
    stack: [u16; 16],

    // Stack pointer.
    sp: u8,

    // General purpose registers v0-vf.
    v0: u8,
    v1: u8,
    v2: u8,
    v3: u8,
    v4: u8,
    v5: u8,
    v6: u8,
    v7: u8,
    v8: u8,
    v9: u8,
    va: u8,
    vb: u8,
    vc: u8,
    vd: u8,
    ve: u8,
    vf: u8,

    // Address register "I".
    i: u16,

    // Timer and sound registers.
    dt: u8,
    st: u8,
}

impl Cpu {
    pub fn new(interconnect: Interconnect) -> Cpu {
        Cpu {
            interconnect: interconnect,
            pc: END_RESERVED as u16,
            ..Cpu::default()
        }
    }

    /// Execute instructions from ram.
    pub fn run(&mut self) {
        loop {
            let word = self.interconnect.read_word(self.pc);

            // Execute until the subroutine ends.
            if self.execute_instruction(word) {
                break
            }
        }
    }

    #[inline(always)]
    fn execute_instruction(&mut self, instr: u16) -> bool {
        let opcode = (instr >> 12) as u8;
        let mut ret: bool = false;
        let mut skip: bool = false;

        //println!("{:x}", instr);

        match opcode {
            0x0 => {
                let identifier = ((instr << 8) >> 8) as u8;

                match identifier {
                    0xE0 => {
                        // 00E0 - CLS
                        // Clears the screen.

                        self.interconnect.clear_display();
                    },
                    0xEE => {
                        // 00EE - RET
                        // Returns from a subroutine.

                        self.sp -= 1;
                        self.pc = self.stack[self.sp as usize];
                        self.stack[self.sp as usize] = 0;

                        // Break out of the execution loop for the current
                        // subroutine.
                        ret = true;
                    },
                    _ => {
                        println!("cpu: {:#?}", self);
                        panic!("Found unknown identifier at instruction: {:#x}, addr: {:#x}", instr, self.pc);
                    },
                }
            },
            0x1 => {
                // 1NNN - JP NNN
                //
                // Jumps to address NNN.

                let addr = ((instr << 4) >> 4) as u16;
                self.pc = addr;
                skip = true;
            },
            0x2 => {
                // 2NNN - CALL NNN
                //
                // Calls subroutine at NNN.

                let addr = ((instr << 4) >> 4) as u16;

                // Add the current program counter to the call stack.
                self.stack[self.sp as usize] = self.pc;
                self.sp += 1;

                // Set the program counter to the call address begin executing
                // the subroutine.
                self.pc = addr;
                self.run();
            },
            0x3 => {
                // 3XNN - SE VX, NN
                //
                // Skips the next instruction if VX equals NN.

                let regx = ((instr << 4) >> 12) as u8;
                let byte = ((instr << 8) >> 8) as u8;
                let x = self.get_reg(regx);

                if x == byte {
                    self.pc += 2;
                }
            }
            0x6 => {
                // 6XNN - LD VX, NN
                //
                // Sets VX to NN.

                let regx = ((instr << 4) >> 12) as u8;
                let byte = ((instr << 8) >> 8) as u8;
                self.set_reg(regx, byte);
            },
            0x7 => {
                // 7XNN - ADD VX, NN
                //
                // Adds NN to VX.

                let regx = ((instr << 4) >> 12) as u8;
                let byte = ((instr << 8) >> 8) as u8;

                let result = self.get_reg(regx) + byte;
                self.set_reg(regx, result);
            },
            0xa => {
                // ANNN - LD I, NNN
                //
                // Sets I to the address NNN.

                let addr = ((instr << 4) >> 4) as u16;
                self.i = addr;
            },
            0xd => {
                // DXYN - DRW VX, VY, N
                //
                // Sprites stored in memory at location in index register (I),
                // 8bits wide. Wraps around the screen. If when drawn, clears a
                // pixel, register VF is set to 1 otherwise it is zero.
                //
                // All drawing is XOR drawing (i.e. it toggles the screen
                // pixels). Sprites are drawn starting at position VX, VY. N is
                // the number of 8bit rows that need to be drawn. If N is
                // greater than 1, second line continues at position VX, VY+1,
                // and so on.

                let regx = ((instr << 4) >> 12) as u8;
                let regy = ((instr << 8) >> 12) as u8;
                let nibble = ((instr << 12) >> 12) as usize;

                // Read N (nibble) bytes out out of memory starting at address
                // register I into our sprite.
                let mut sprite = vec![0 as u8; nibble];
                for i in 0..nibble {
                    sprite[i] = self.interconnect.ram[self.i as usize + i];
                }

                // Get screen coordinates from the requested registers.
                let x = self.get_reg(regx);
                let y = self.get_reg(regy);

                // Draw the sprite and store collision detection results in vf.
                self.vf = self.interconnect.draw(x as usize, y as usize, sprite);
            },
            0xf => {
                let regx = ((instr << 4) >> 12) as u8;
                let identifier = ((instr << 8) >> 8) as u8;

                match identifier {
                    0x07 => {
                        // FX07 - LD VX, DT
                        //
                        // Sets VX to the value of the delay timer.

                        let dt = self.dt;
                        self.set_reg(regx, dt);
                    },
                    0x15 => {
                        // FX15 - LD DT, VX
                        //
                        // Sets the delay timer to VX.

                        let x: u8 = self.get_reg(regx);
                        self.dt = x;
                    },
                    0x29 => {
                        // FX29 - LD F, VX
                        //
                        // Sets I to the location of the sprite for the
                        // character in VX. Characters 0-F (in hexadecimal) are
                        // represented by a 4x5 font.

                        let x: u8 = self.get_reg(regx);
                        self.i = self.interconnect.get_font(x);
                    },
                    0x33 => {
                        // FX33 - LD B, VX
                        //
                        // Stores the Binary-coded decimal representation of VX,
                        // with the most significant of three digits at the
                        // address in I, the middle digit at I plus 1, and the
                        // least significant digit at I plus 2. (In other words,
                        // take the decimal representation of VX, place the
                        // hundreds digit in memory at location in I, the tens
                        // digit at location I+1, and the ones digit at
                        // location I+2.)

                        const DECIMAL_LENGTH: usize = 3;

                        let mut x: u8 = self.get_reg(regx);
                        let mut digits = vec![0 as u8; DECIMAL_LENGTH];
                        let mut digit_count: usize = 0;

                        // Organize the digits in the decimal into a slice.
                        while x > 0 {
                            digit_count += 1;
                            digits[DECIMAL_LENGTH - digit_count] = x % 10;
                            x /= 10;
                        }

                        // Set I, I+1, and I+3 to the values of the digits.
                        let i: usize = self.i as usize;
                        self.interconnect.ram[i] = digits[0];
                        self.interconnect.ram[i + 1] = digits[1];
                        self.interconnect.ram[i + 2] = digits[2];
                    },
                    0x65 => {
                        // FX65 - LD VX, [I]
                        //
                        // Fills V0 to VX with values from memory starting at
                        // address I.

                        let i: usize = self.i as usize;
                        let end_reg = (regx + 1) as usize;

                        for register in 0x0..end_reg {
                            let mem = self.interconnect.ram[i + register];
                            self.set_reg(register as u8, mem);
                        }
                    },
                    _ => {
                        println!("cpu: {:#?}", self);
                        panic!("Found unknown identifier at instruction: {:#x}, addr: {:#x}", instr, self.pc);
                    },
                }
            },
            _ => {
                println!("cpu: {:#?}", self);
                panic!("Found unknown opcode at instruction: {:#x}, addr: {:#x}", instr, self.pc);
            },
        }

        // Increment the program counter to the next instruction.
        if !ret && !skip {
            self.pc += INSTRUCTION_SIZE;
        }

        self.handle_timers();

        // By default the execution loop in not broken. True will be returned
        // only by a successful RET instruction is executed.
        ret
    }

    /// Handle the delay timer and play sounds.
    fn handle_timers(&mut self) {
        let dt_enabled = self.dt > 0;
        let st_enabled = self.st > 0;

        if dt_enabled || st_enabled {
            println!("SLEEPY TIME: {:x}", self.dt);
            sleep(Duration::from_millis(TIMER_DELAY));

            if dt_enabled {
                self.dt -= 1;
            }
            if st_enabled {
                self.st -= 1;
            }
        }
    }

    /// Gets the value at a specified register.
    fn get_reg(&mut self, reg: u8) -> u8 {
        match reg {
            0x0 => self.v0,
            0x1 => self.v1,
            0x2 => self.v2,
            0x3 => self.v3,
            0x4 => self.v4,
            0x5 => self.v5,
            0x6 => self.v6,
            0x7 => self.v7,
            0x8 => self.v8,
            0x9 => self.v9,
            0xa => self.va,
            0xb => self.vb,
            0xc => self.vc,
            0xd => self.vd,
            0xe => self.ve,
            0xf => self.vf,
            _ => {
                panic!("Cannot get unknown register: V{:X}", reg);
            }
        }
    }

    /// Sets the value of a general purpose register.
    fn set_reg(&mut self, reg: u8, byte: u8) {
        match reg {
            0x0 => self.v0 = byte,
            0x1 => self.v1 = byte,
            0x2 => self.v2 = byte,
            0x3 => self.v3 = byte,
            0x4 => self.v4 = byte,
            0x5 => self.v5 = byte,
            0x6 => self.v6 = byte,
            0x7 => self.v7 = byte,
            0x8 => self.v8 = byte,
            0x9 => self.v9 = byte,
            0xa => self.va = byte,
            0xb => self.vb = byte,
            0xc => self.vc = byte,
            0xd => self.vd = byte,
            0xe => self.ve = byte,
            0xf => self.vf = byte,
            _ => {
                panic!("Cannot set unknown register: V{:X}", reg);
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::bus::{Bus, Addressable};
use super::byteorder::{ByteOrder, LittleEndian};
use super::registers::*;

enum Condition {
    None,
    Z,
    C,
    Nz,
    Nc
}

pub struct Cpu {
    regs: Registers,
    bus: Bus
}

impl Cpu {
    pub fn new(bus: Bus) -> Cpu {
        Cpu {
            regs: Registers::default(),
            bus: bus
        }
    }

    pub fn power_on(&mut self) {
        self.regs.a = 0x01;
        self.regs.b = 0x13;
        self.regs.c = 0x00;
        self.regs.d = 0xD8;
        self.regs.e = 0x00;
        self.regs.flags = 0xB0;
        self.regs.h = 0x4D;
        self.regs.l = 0x01;
        self.regs.sp = 0xFFFE;
        self.regs.pc = 0x100;
    }

    pub fn step(&mut self) -> usize {
        let opcode = self.inc_imm_byte();
        self.execute(opcode)
    }

    fn inc_imm_byte(&mut self) -> u8 {
        let byte = self.bus.read(self.regs.pc);
        self.regs.pc = self.regs.pc + 1;

        byte
    }

    fn inc_imm_word(&mut self) -> u16 {
        let word = &[self.bus.read(self.regs.pc), self.bus.read(self.regs.pc+1)];
        self.regs.pc = self.regs.pc + 2;

        LittleEndian::read_u16(word)
    }

    fn execute(&mut self, opcode: u8) -> usize {
        use super::registers::Register8::*;
        use super::registers::Register16::*;

        match opcode {
            0x00 => { self.nop(); 4 },
            0x01 => { self.ld_rr_d16(BC); 12 },
            0x02 => { self.ld_indrr_a(BC); 8 },
            0x03 => { self.inc_rr(BC); 8 },
            0x04 => { self.inc_r(B); 4 },
            0x05 => { self.dec_r(B); 4 },
            0x06 => { self.ld_r_d8(B); 8 },
            0x07 => { self.rlca(); 4 },
            0x08 => { self.ld_a16_sp(); 20 },
            0x09 => { self.add_rr_rr(HL, BC); 8 },
            0x0A => { self.ld_a_indrr(BC); 8 },
            0x0B => { self.dec_rr(BC); 8 },
            0x0C => { self.inc_r(C); 4 },
            0x0D => { self.dec_r(C); 4 },
            0x0E => { self.ld_r_d8(C); 8 },
            0x0F => { self.rrca(); 4 },
            _ => panic!("Unknown opcode: {:#X}", opcode)
        }
    }

    fn condition_met(&self, cond: Condition) -> bool {
        match cond {
            Condition::None => true,
            Condition::C => self.regs.is_flag_set(Flag::C),
            Condition::Z => self.regs.is_flag_set(Flag::Z),
            Condition::Nc => !self.regs.is_flag_set(Flag::C),
            Condition::Nz => !self.regs.is_flag_set(Flag::Z)
        }
    }

    /*
     * 8-bit load instructions
     */

    // LD r, d8
    #[inline(always)]
    fn ld_r_d8(&mut self, dest: Register8) {
        let val = self.inc_imm_byte();
        self.regs.write_u8(&dest, val);
    }

    // LD r, r
    #[inline(always)]
    fn ld_r_r(&mut self, dest: Register8, src: Register8) {
        let val = self.regs.read_u8(&src);
        self.regs.write_u8(&dest, val);
    }

    // LD (rr), A
    #[inline(always)]
    fn ld_indrr_a(&mut self, dest: Register16) {
        let addr = self.regs.read_u16(&dest);
        let val = self.regs.a;
        self.bus.write(addr, val);
    }

    // LD A, (rr)
    #[inline(always)]
    fn ld_a_indrr(&mut self, src: Register16) {
        let addr = self.regs.read_u16(&src);
        let val = self.bus.read(addr);
        self.regs.a = val;
    }

    /*
     * 8-bit math instructions
     */

    // INC r
    // Affects flags: Z, N, H
    #[inline(always)]
    fn inc_r(&mut self, reg: Register8) {
        let val = self.regs.read_u8(&reg);
        let increased = val.wrapping_add(1);

        self.regs.write_u8(&reg, increased);

        self.regs.flags =
            (if increased == 0 { 1 << 7 } else { 0 })   // Z
            | (((val & 0xF) + 1) & 0b00010000) << 1     // H
            | self.regs.flags & (Flag::C as u8)         // C

    }

    // DEC r
    // Affects flags: Z, N, H
    #[inline(always)]
    fn dec_r(&mut self, reg: Register8) {
        let val = self.regs.read_u8(&reg);
        let decreased = val.wrapping_sub(1);

        self.regs.write_u8(&reg, decreased);

        self.regs.flags =
            (if decreased == 0 { 1 << 7 } else { 0 })                   // Z
            | Flag::N as u8                                             // N
            | if (((val & 0xF0) - 1) & 0b00001000) == 0b00001000        // H
                { 1 << 6 }
                else { 0 }
            | self.regs.flags & (Flag::C as u8)                         // C
    }

    /*
     * 8-bit bit instructions
     */

    // RLCA
    // Affects flags: Z, N, H, C
    fn rlca(&mut self) {
        let val = self.regs.a;
        let adj = val << 1;

        self.regs.a = adj;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | (val & 0b10000000) >> 3           // C
    }

    // RRCA
    // Affects flags: Z, N, H, C
    fn rrca(&mut self) {
        let val = self.regs.a;
        let adj = val >> 1;

        self.regs.a = adj;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | val << 4                          // C
    }

    /*
     * 16-bit load instructions
     */

     // LD rr, d16
    #[inline(always)]
    fn ld_rr_d16(&mut self, dest: Register16) {
        let val = self.inc_imm_word();
        self.regs.write_u16(&dest, val);
    }

    // LD (a16), SP
    #[inline(always)]
    fn ld_a16_sp(&mut self) {
        let addr = self.inc_imm_word();
        self.bus.write(addr, (self.regs.sp & 0x00FF) as u8);
        self.bus.write(addr + 1, (self.regs.sp >> 8) as u8);
    }

    /*
     * 16-bit math instructions
     */

    // INC rr
    #[inline(always)]
    fn inc_rr(&mut self, reg: Register16) {
        let val = self.regs.read_u16(&reg);
        self.regs.write_u16(&reg, val.wrapping_add(1));
    }

    // DEC rr
    #[inline(always)]
    fn dec_rr(&mut self, reg: Register16) {
        let val = self.regs.read_u16(&reg);
        self.regs.write_u16(&reg, val.wrapping_sub(1));
    }

    // ADD rr, rr
    // Affects flags: N, H, C
    #[inline(always)]
    fn add_rr_rr(&mut self, dest: Register16, src: Register16) {
        let src_val = self.regs.read_u16(&src);
        let dest_val = self.regs.read_u16(&dest);

        self.regs.write_u16(&dest, dest_val.wrapping_add(src_val));

        let src_high = ((src_val & 0xF0) >> 8) as u8;
        let dest_high = ((dest_val & 0xF0) >> 8) as u8;

        self.regs.flags =
            (self.regs.flags & Flag::Z as u8) // Z
            | (((dest_high & 0xF) + (src_high & 0xF)) & 0b00010000) << 1    // H
            | if dest_val.wrapping_add(src_val) < src_val                   // C
                { Flag::C as u8 }
                else { 0 };
    }

    /*
     * Misc instructions
     */

     // NOP
    #[inline(always)]
    fn nop(&self) {
        // Ahh, doing nothing feels so good!
    }
}<commit_msg>Added another set of instructions.<commit_after>use super::bus::{Bus, Addressable};
use super::byteorder::{ByteOrder, LittleEndian};
use super::registers::*;

enum Condition {
    None,
    Z,
    C,
    Nz,
    Nc
}

pub struct Cpu {
    regs: Registers,
    bus: Bus
}

impl Cpu {
    pub fn new(bus: Bus) -> Cpu {
        Cpu {
            regs: Registers::default(),
            bus: bus
        }
    }

    pub fn power_on(&mut self) {
        self.regs.a = 0x01;
        self.regs.b = 0x13;
        self.regs.c = 0x00;
        self.regs.d = 0xD8;
        self.regs.e = 0x00;
        self.regs.flags = 0xB0;
        self.regs.h = 0x4D;
        self.regs.l = 0x01;
        self.regs.sp = 0xFFFE;
        self.regs.pc = 0x100;
    }

    pub fn step(&mut self) -> usize {
        let opcode = self.inc_imm_byte();
        self.execute(opcode)
    }

    fn inc_imm_byte(&mut self) -> u8 {
        let byte = self.bus.read(self.regs.pc);
        self.regs.pc = self.regs.pc + 1;

        byte
    }

    fn inc_imm_word(&mut self) -> u16 {
        let word = &[self.bus.read(self.regs.pc), self.bus.read(self.regs.pc+1)];
        self.regs.pc = self.regs.pc + 2;

        LittleEndian::read_u16(word)
    }

    fn execute(&mut self, opcode: u8) -> usize {
        use super::registers::Register8::*;
        use super::registers::Register16::*;

        match opcode {
            0x00 => { self.nop(); 4 },
            0x01 => { self.ld_rr_d16(BC); 12 },
            0x02 => { self.ld_indrr_a(BC); 8 },
            0x03 => { self.inc_rr(BC); 8 },
            0x04 => { self.inc_r(B); 4 },
            0x05 => { self.dec_r(B); 4 },
            0x06 => { self.ld_r_d8(B); 8 },
            0x07 => { self.rlca(); 4 },
            0x08 => { self.ld_a16_sp(); 20 },
            0x09 => { self.add_rr_rr(HL, BC); 8 },
            0x0A => { self.ld_a_indrr(BC); 8 },
            0x0B => { self.dec_rr(BC); 8 },
            0x0C => { self.inc_r(C); 4 },
            0x0D => { self.dec_r(C); 4 },
            0x0E => { self.ld_r_d8(C); 8 },
            0x0F => { self.rrca(); 4 },

            0x10 => { self.stop(); 4 },
            0x11 => { self.ld_rr_d16(DE); 12 },
            0x12 => { self.ld_indrr_a(DE); 8 },
            0x13 => { self.inc_rr(DE); 8 },
            0x14 => { self.inc_r(D); 4 },
            0x15 => { self.dec_r(D); 4 },
            0x16 => { self.ld_r_d8(D); 8 },
            0x17 => { self.rla(); 4 },
            0x18 => { self.jr(Condition::None); 12 },
            0x19 => { self.add_rr_rr(HL, DE); 8 },
            0x1A => { self.ld_a_indrr(DE); 8 },
            0x1B => { self.dec_rr(DE); 8 },
            0x1C => { self.inc_r(E); 4 },
            0x1D => { self.dec_r(E); 4 },
            0x1E => { self.ld_r_d8(E); 8 },
            0x1F => { self.rra(); 4 },

            _ => panic!("Unknown opcode: {:#X}", opcode)
        }
    }

    fn condition_met(&self, cond: Condition) -> bool {
        match cond {
            Condition::None => true,
            Condition::C => self.regs.is_flag_set(Flag::C),
            Condition::Z => self.regs.is_flag_set(Flag::Z),
            Condition::Nc => !self.regs.is_flag_set(Flag::C),
            Condition::Nz => !self.regs.is_flag_set(Flag::Z)
        }
    }

    /*
     * 8-bit load instructions
     */

    // LD r, d8
    #[inline(always)]
    fn ld_r_d8(&mut self, dest: Register8) {
        let val = self.inc_imm_byte();
        self.regs.write_u8(&dest, val);
    }

    // LD r, r
    #[inline(always)]
    fn ld_r_r(&mut self, dest: Register8, src: Register8) {
        let val = self.regs.read_u8(&src);
        self.regs.write_u8(&dest, val);
    }

    // LD (rr), A
    #[inline(always)]
    fn ld_indrr_a(&mut self, dest: Register16) {
        let addr = self.regs.read_u16(&dest);
        let val = self.regs.a;
        self.bus.write(addr, val);
    }

    // LD A, (rr)
    #[inline(always)]
    fn ld_a_indrr(&mut self, src: Register16) {
        let addr = self.regs.read_u16(&src);
        let val = self.bus.read(addr);
        self.regs.a = val;
    }

    /*
     * 8-bit math instructions
     */

    // INC r
    // Affects flags: Z, N, H
    #[inline(always)]
    fn inc_r(&mut self, reg: Register8) {
        let val = self.regs.read_u8(&reg);
        let increased = val.wrapping_add(1);

        self.regs.write_u8(&reg, increased);

        self.regs.flags =
            (if increased == 0 { 1 << 7 } else { 0 })   // Z
            | (((val & 0xF) + 1) & 0b00010000) << 1     // H
            | self.regs.flags & (Flag::C as u8)         // C

    }

    // DEC r
    // Affects flags: Z, N, H
    #[inline(always)]
    fn dec_r(&mut self, reg: Register8) {
        let val = self.regs.read_u8(&reg);
        let decreased = val.wrapping_sub(1);

        self.regs.write_u8(&reg, decreased);

        self.regs.flags =
            (if decreased == 0 { 1 << 7 } else { 0 })                   // Z
            | Flag::N as u8                                             // N
            | if (((val & 0xF0) - 1) & 0b00001000) == 0b00001000        // H
                { 1 << 6 }
                else { 0 }
            | self.regs.flags & (Flag::C as u8)                         // C
    }

    /*
     * 8-bit bit instructions
     */

    // RLCA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rlca(&mut self) {
        let val = self.regs.a;
        let adj = val << 1;
        let carry = (val >> 7) & 0b00000001;

        self.regs.a = adj | carry;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | carry << 4          // C
    }

    // RLA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rla(&mut self) {
        let val = self.regs.a;
        let adj = (val << 1) | ((self.regs.flags & Flag::C as u8) >> 4);

        self.regs.a = adj;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | (val & 0b10000000) >> 3           // C
    }

    // RRCA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rrca(&mut self) {
        let val = self.regs.a;
        let adj = val >> 1;
        let carry = val & 0b00000001;

        self.regs.a = adj | (carry << 7);

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | carry << 4                        // C
    }

    // RRA
    // Affects flags: Z, N, H, C
    #[inline(always)]
    fn rra(&mut self) {
        let val = self.regs.a;
        let adj = (val >> 1) | ((self.regs.flags & Flag::C as u8) << 3);

        self.regs.a = adj;

        self.regs.flags =
            (if adj == 0 { 1 << 7 } else { 0 }) // Z
            | adj << 4                          // C
    }

    /*
     * 16-bit load instructions
     */

     // LD rr, d16
    #[inline(always)]
    fn ld_rr_d16(&mut self, dest: Register16) {
        let val = self.inc_imm_word();
        self.regs.write_u16(&dest, val);
    }

    // LD (a16), SP
    #[inline(always)]
    fn ld_a16_sp(&mut self) {
        let addr = self.inc_imm_word();
        self.bus.write(addr, (self.regs.sp & 0x00FF) as u8);
        self.bus.write(addr + 1, (self.regs.sp >> 8) as u8);
    }

    /*
     * 16-bit math instructions
     */

    // INC rr
    #[inline(always)]
    fn inc_rr(&mut self, reg: Register16) {
        let val = self.regs.read_u16(&reg);
        self.regs.write_u16(&reg, val.wrapping_add(1));
    }

    // DEC rr
    #[inline(always)]
    fn dec_rr(&mut self, reg: Register16) {
        let val = self.regs.read_u16(&reg);
        self.regs.write_u16(&reg, val.wrapping_sub(1));
    }

    // ADD rr, rr
    // Affects flags: N, H, C
    #[inline(always)]
    fn add_rr_rr(&mut self, dest: Register16, src: Register16) {
        let src_val = self.regs.read_u16(&src);
        let dest_val = self.regs.read_u16(&dest);

        self.regs.write_u16(&dest, dest_val.wrapping_add(src_val));

        let src_high = ((src_val & 0xF0) >> 8) as u8;
        let dest_high = ((dest_val & 0xF0) >> 8) as u8;

        self.regs.flags =
            (self.regs.flags & Flag::Z as u8) // Z
            | (((dest_high & 0xF) + (src_high & 0xF)) & 0b00010000) << 1    // H
            | if dest_val.wrapping_add(src_val) < src_val                   // C
                { Flag::C as u8 }
                else { 0 };
    }

    // JR c, r8
    #[inline(always)]
    fn jr(&mut self, condition: Condition) {
        let pc = self.regs.pc;
        let offset = self.inc_imm_byte() as i16;

        if (offset > 0) {
            self.regs.pc = pc.wrapping_add(offset as u16);
        } else {
            self.regs.pc = pc.wrapping_sub(offset.abs() as u16);
        }
    }

    /*
     * Misc instructions
     */

     // NOP
    #[inline(always)]
    fn nop(&self) {
        // Ahh, doing nothing feels so good!
    }

    // STOP 0
    // TODO: halt cpu/lcd
    #[inline(always)]
    fn stop(&mut self) {
        // This instruction is 2 bytes.
        self.inc_imm_byte();
    }
}<|endoftext|>


<commit_before>//! DNS Resolution

use log::Level::Info;
use std::io::{stderr, Write};
use async_std::net::{SocketAddr, ToSocketAddrs};

use super::results::{CabotError, CabotResult};

pub struct Resolver {
    verbose: bool,
}

impl Resolver {
    pub fn new(verbose: bool) -> Self {
        Resolver { verbose }
    }
    pub async fn get_addr(&self, authority: &str, ipv4: bool, ipv6: bool) -> CabotResult<SocketAddr> {
        debug!("Resolving TCP Endpoint for authority {}", authority);
        let addrs = authority.to_socket_addrs().await?;
        let addr = addrs
            .filter(|addr| (ipv4 && addr.is_ipv4()) || (ipv6 && addr.is_ipv6()))
            .next()
            .ok_or(CabotError::DNSLookupError(
                "Host does not exists".to_owned(),
            ))?;
        if log_enabled!(Info) {
            info!("Authority {} has been resolved to {}", authority, addr);
        } else if self.verbose {
            writeln!(
                &mut stderr(),
                "* Authority {} has been resolved to {}",
                authority,
                addr
            )
            .unwrap();
        }
        Ok(addr)
    }
}
<commit_msg>Add a timeout for the dns resolution<commit_after>//! DNS Resolution

use std::io::{stderr, Write};
use std::time::Duration;

use async_std::io;
use async_std::net::{SocketAddr, ToSocketAddrs};
use log::Level::Info;

use super::results::{CabotError, CabotResult};

pub struct Resolver {
    verbose: bool,
}

impl Resolver {
    pub fn new(verbose: bool) -> Self {
        Resolver { verbose }
    }
    pub async fn get_addr(
        &self,
        authority: &str,
        ipv4: bool,
        ipv6: bool,
    ) -> CabotResult<SocketAddr> {
        debug!("Resolving TCP Endpoint for authority {}", authority);

        let addrs = io::timeout(Duration::from_secs(10), async {
            authority.to_socket_addrs().await
        })
        .await?;

        let addr = addrs
            .filter(|addr| (ipv4 && addr.is_ipv4()) || (ipv6 && addr.is_ipv6()))
            .next()
            .ok_or(CabotError::DNSLookupError(
                "Host does not exists".to_owned(),
            ))?;
        if log_enabled!(Info) {
            info!("Authority {} has been resolved to {}", authority, addr);
        } else if self.verbose {
            writeln!(
                &mut stderr(),
                "* Authority {} has been resolved to {}",
                authority,
                addr
            )
            .unwrap();
        }
        Ok(addr)
    }
}
<|endoftext|>


<commit_before>extern crate chrono;

use self::chrono::*;

pub enum IssuePattern { IntensityOnly, LowAccuracy, HighAccuracy, Cancel }
pub enum Source { Sapporo, Sendai, Tokyo, Osaka, Fukuoka, Okinawa }
pub enum Kind { Normal, Drill, Cancel, DrillCancel, Reference, Test }
pub enum Status { Normal, Correction, CancelCorrection, LastWithCorrection, Last, Unknown }

pub enum EpicenterAccuracy {
	Single, Territory, GridSearchLow, GridSearchHigh,
	NIEDLow, NIEDHigh, EPOSLow, EPOSHigh, Reserved, Unknown
}

pub enum DepthAccuracy {
	Single, Territory, GridSearchLow, GridSearchHigh,
	NIEDLow, NIEDHigh, EPOSLow, EPOSHigh, Reserved, Unknown
}

pub enum MagnitudeAccuracy {
	NIED, PWave, PSMixed, SWave, EPOS, Level,
	Undefined, Reserved, Unknown
}

pub enum EpicenterCategory { Land, Sea, Undefined, Unknown }
pub enum WarningStatus { Forecast, Alert, Undefined, Unknown }
pub enum IntensityChange { Same, Up, Down, Undefined, Unknown }
pub enum ChangeReason { Nothing, Magnitude, Epicenter, Mixed, Depth, Undefined, Unknown }
pub enum WaveStatus { Unreached, Reached, Undefined, Unknown }

pub struct AreaEEW {

	area_name: String,
	minimum_intensity: f32,
	maximum_intensity: Option<f32>,
	reached_at: DateTime<UTC>,
	warning_status: WarningStatus,
	wave_status: WaveStatus,
}

pub struct EEW {

	pattern: IssuePattern,
	source: Source,
	kind: Kind,
	issued_at: DateTime<UTC>,

	occurred_at: DateTime<UTC>,
	id: String,
	status: Status,
	number: Option<u32>,
	epicenter_name: String,

	epicenter: (f32, f32),
	depth: f32,
	magnitude: f32,
	maximum_intensity: f32,

	epicenter_accuracy: EpicenterAccuracy,
	depth_accuracy: DepthAccuracy,
	magnitude_accuracy: MagnitudeAccuracy,

	epicenter_caterogy: EpicenterCategory,
	warning_status: WarningStatus,
	intensity_change: IntensityChange,
	change_reason: ChangeReason,

	area_eew: Vec<AreaEEW>,
}
<commit_msg>Add ToEEW trait<commit_after>extern crate chrono;

use self::chrono::*;

pub enum IssuePattern { IntensityOnly, LowAccuracy, HighAccuracy, Cancel }
pub enum Source { Sapporo, Sendai, Tokyo, Osaka, Fukuoka, Okinawa }
pub enum Kind { Normal, Drill, Cancel, DrillCancel, Reference, Test }
pub enum Status { Normal, Correction, CancelCorrection, LastWithCorrection, Last, Unknown }

pub enum EpicenterAccuracy {
	Single, Territory, GridSearchLow, GridSearchHigh,
	NIEDLow, NIEDHigh, EPOSLow, EPOSHigh, Reserved, Unknown
}

pub enum DepthAccuracy {
	Single, Territory, GridSearchLow, GridSearchHigh,
	NIEDLow, NIEDHigh, EPOSLow, EPOSHigh, Reserved, Unknown
}

pub enum MagnitudeAccuracy {
	NIED, PWave, PSMixed, SWave, EPOS, Level,
	Undefined, Reserved, Unknown
}

pub enum EpicenterCategory { Land, Sea, Undefined, Unknown }
pub enum WarningStatus { Forecast, Alert, Undefined, Unknown }
pub enum IntensityChange { Same, Up, Down, Undefined, Unknown }
pub enum ChangeReason { Nothing, Magnitude, Epicenter, Mixed, Depth, Undefined, Unknown }
pub enum WaveStatus { Unreached, Reached, Undefined, Unknown }

pub struct AreaEEW {

	area_name: String,
	minimum_intensity: f32,
	maximum_intensity: Option<f32>,
	reached_at: DateTime<UTC>,
	warning_status: WarningStatus,
	wave_status: WaveStatus,
}

pub struct EEW {

	pattern: IssuePattern,
	source: Source,
	kind: Kind,
	issued_at: DateTime<UTC>,

	occurred_at: DateTime<UTC>,
	id: String,
	status: Status,
	number: Option<u32>,
	epicenter_name: String,

	epicenter: (f32, f32),
	depth: f32,
	magnitude: f32,
	maximum_intensity: f32,

	epicenter_accuracy: EpicenterAccuracy,
	depth_accuracy: DepthAccuracy,
	magnitude_accuracy: MagnitudeAccuracy,

	epicenter_caterogy: EpicenterCategory,
	warning_status: WarningStatus,
	intensity_change: IntensityChange,
	change_reason: ChangeReason,

	area_eew: Vec<AreaEEW>,
}

pub trait ToEEW {
	fn to_eew(&self, text: &str) -> EEW;
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{Read, Seek, Cursor};
use std::io::{SeekFrom, Error, ErrorKind};
use std::convert::AsMut;

extern crate uuid;
extern crate byteorder;
use self::byteorder::{LittleEndian, ReadBytesExt, BigEndian};
use self::uuid::Uuid;
#[derive(Debug)]
pub struct Header
{
	pub signature: String, // EFI PART
	pub revision: u32, // 00 00 01 00
	pub header_size_le: u32, // little endian
	pub crc32: u32,
	pub reserved: u32, // must be 0
	pub current_lba: u64,
	pub backup_lba: u64,
	pub first_usable: u64,
	pub last_usable: u64,
	pub disk_guid: uuid::Uuid,
	pub start_lba: u64,
	pub num_parts: u32,
	pub part_size: u32, // usually 128
	pub crc32_parts: u32
}

fn parse_uuid(rdr: &mut Cursor<&[u8]>) -> Result<Uuid, Error>
{
	//let mut rdr = Cursor::new(bytes);
	let d1: u32 = rdr.read_u32::<LittleEndian>().unwrap();
	let d2: u16 = rdr.read_u16::<LittleEndian>().unwrap();
	let d3: u16 = rdr.read_u16::<LittleEndian>().unwrap();

	match Uuid::from_fields(d1, d2, d3, &rdr.get_ref()[8..])
	{
		Ok(uuid) => Ok(uuid),
		Err(_) => Err(Error::new(ErrorKind::Other, "Invalid Disk UUID?"))
	}
}

fn clone_into_array<A, T>(slice: &[T]) -> A
    where A: Sized + Default + AsMut<[T]>,
          T: Clone
{
    let mut a = Default::default();
    <A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
    a
}

pub fn read_header2(path:&String) -> Result<Header, Error>
{
	let mut file = File::open(path)?;
	let _ = file.seek(SeekFrom::Start(512));

	let mut hdr: [u8; 92] = [0; 92];

	let _ = file.read_exact(&mut hdr);
	let mut reader = Cursor::new(&hdr[..]);

	let sigstr = reader.read_u64::<LittleEndian>()?.to_string();

	if sigstr != "EFI PART"
	{
		return Err(Error::new(ErrorKind::Other, "Invalid GPT Signature."))
	};

	let h = Header{
		signature:      sigstr.to_string(),
		revision:       reader.read_u32::<LittleEndian>().unwrap(),
		header_size_le: reader.read_u32::<LittleEndian>().unwrap(),
		crc32:          reader.read_u32::<LittleEndian>().unwrap(),
		reserved:       reader.read_u32::<LittleEndian>().unwrap(),
		current_lba:    reader.read_u64::<LittleEndian>().unwrap(),
		backup_lba:     reader.read_u64::<LittleEndian>().unwrap(),
		first_usable:   reader.read_u64::<LittleEndian>().unwrap(),
		last_usable:    reader.read_u64::<LittleEndian>().unwrap(),
		disk_guid:      parse_uuid(&mut reader)?,
		start_lba:      reader.read_u64::<LittleEndian>().unwrap(),
		num_parts:      reader.read_u32::<LittleEndian>().unwrap(),
		part_size:      reader.read_u32::<LittleEndian>().unwrap(),
		crc32_parts:    reader.read_u32::<LittleEndian>().unwrap()
	};

	Ok(h)
}
/*
pub fn read_header(path:&String) -> Result<Header, Error>
{
	let mut file = File::open(path)?;
	let _ = file.seek(SeekFrom::Start(512))?;

	let mut signature: [u8;8] = [0;8];
	let _ = file.read_exact(&mut signature);
	let sigstr = String::from_utf8_lossy(&signature);
	if sigstr.as_ref() != "EFI PART" { return Err(Error::new(ErrorKind::Other, "Invalid GPT Signature")) };

	let mut revision: [u8; 4] = [0; 4];
	let mut header_size_le: [u8;4] = [0; 4];
	let mut crc32: [u8;4] = [0; 4];
	let mut reserved: [u8;4] = [0; 4];
	let mut current_lba: [u8;8] = [0; 8];
	let mut backup_lba: [u8;8] = [0; 8];
	let mut first_usable: [u8;8] = [0; 8];
	let mut last_usable: [u8;8] = [0; 8];
	let mut disk_guid: [u8;16] = [0; 16];
	let mut start_lba: [u8; 8] = [0; 8];
	let mut num_parts: [u8; 4] = [0; 4];
	let mut part_size: [u8; 4]= [0; 4];
	let mut crc32_parts: [u8; 4] = [0; 4];

	let _ = file.read_exact(&mut revision);
	let _ = file.read_exact(&mut header_size_le);
	let _ = file.read_exact(&mut crc32);
	let _ = file.read_exact(&mut reserved);
	let _ = file.read_exact(&mut current_lba);
	let _ = file.read_exact(&mut backup_lba);
	let _ = file.read_exact(&mut first_usable);
	let _ = file.read_exact(&mut last_usable);
	let _ = file.read_exact(&mut disk_guid);
	let _ = file.read_exact(&mut start_lba);
	let _ = file.read_exact(&mut num_parts);
	let _ = file.read_exact(&mut part_size);
	let _ = file.read_exact(&mut crc32_parts);

	return Ok(Header{
		signature: signature,
		revision: revision,
		header_size_le: header_size_le,
		crc32: crc32,
		reserved: reserved,
		current_lba: current_lba,
		backup_lba: backup_lba,
		first_usable: first_usable,
		last_usable: last_usable,
		disk_guid: parse_uuid(&disk_guid)?,
		start_lba: start_lba,
		num_parts: num_parts,
		part_size: part_size,
		crc32_parts: crc32_parts
	});
}
*/
<commit_msg>Remove unwraps<commit_after>use std::fs::File;
use std::io::{Read, Seek, Cursor};
use std::io::{SeekFrom, Error, ErrorKind};
use std::convert::AsMut;

extern crate uuid;
extern crate byteorder;
use self::byteorder::{LittleEndian, ReadBytesExt, BigEndian};
use self::uuid::Uuid;
#[derive(Debug)]
pub struct Header
{
	pub signature: String, // EFI PART
	pub revision: u32, // 00 00 01 00
	pub header_size_le: u32, // little endian
	pub crc32: u32,
	pub reserved: u32, // must be 0
	pub current_lba: u64,
	pub backup_lba: u64,
	pub first_usable: u64,
	pub last_usable: u64,
	pub disk_guid: uuid::Uuid,
	pub start_lba: u64,
	pub num_parts: u32,
	pub part_size: u32, // usually 128
	pub crc32_parts: u32
}

fn parse_uuid(rdr: &mut Cursor<&[u8]>) -> Result<Uuid, Error>
{
	//let mut rdr = Cursor::new(bytes);
	let d1: u32 = rdr.read_u32::<LittleEndian>()?;
	let d2: u16 = rdr.read_u16::<LittleEndian>()?;
	let d3: u16 = rdr.read_u16::<LittleEndian>()?;

	match Uuid::from_fields(d1, d2, d3, &rdr.get_ref()[8..])
	{
		Ok(uuid) => Ok(uuid),
		Err(_) => Err(Error::new(ErrorKind::Other, "Invalid Disk UUID?"))
	}
}

fn clone_into_array<A, T>(slice: &[T]) -> A
    where A: Sized + Default + AsMut<[T]>,
          T: Clone
{
    let mut a = Default::default();
    <A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
    a
}

pub fn read_header2(path:&String) -> Result<Header, Error>
{
	let mut file = File::open(path)?;
	let _ = file.seek(SeekFrom::Start(512));

	let mut hdr: [u8; 92] = [0; 92];

	let _ = file.read_exact(&mut hdr);
	let mut reader = Cursor::new(&hdr[..]);

	let sigstr = reader.read_u64::<LittleEndian>()?.to_string();

	if sigstr != "EFI PART"
	{
		return Err(Error::new(ErrorKind::Other, "Invalid GPT Signature."))
	};

	let h = Header{
		signature:      sigstr.to_string(),
		revision:       reader.read_u32::<LittleEndian>()?,
		header_size_le: reader.read_u32::<LittleEndian>()?,
		crc32:          reader.read_u32::<LittleEndian>()?,
		reserved:       reader.read_u32::<LittleEndian>()?,
		current_lba:    reader.read_u64::<LittleEndian>()?,
		backup_lba:     reader.read_u64::<LittleEndian>()?,
		first_usable:   reader.read_u64::<LittleEndian>()?,
		last_usable:    reader.read_u64::<LittleEndian>()?,
		disk_guid:      parse_uuid(&mut reader)?,
		start_lba:      reader.read_u64::<LittleEndian>()?,
		num_parts:      reader.read_u32::<LittleEndian>()?,
		part_size:      reader.read_u32::<LittleEndian>()?,
		crc32_parts:    reader.read_u32::<LittleEndian>()?,
	};

	Ok(h)
}
/*
pub fn read_header(path:&String) -> Result<Header, Error>
{
	let mut file = File::open(path)?;
	let _ = file.seek(SeekFrom::Start(512))?;

	let mut signature: [u8;8] = [0;8];
	let _ = file.read_exact(&mut signature);
	let sigstr = String::from_utf8_lossy(&signature);
	if sigstr.as_ref() != "EFI PART" { return Err(Error::new(ErrorKind::Other, "Invalid GPT Signature")) };

	let mut revision: [u8; 4] = [0; 4];
	let mut header_size_le: [u8;4] = [0; 4];
	let mut crc32: [u8;4] = [0; 4];
	let mut reserved: [u8;4] = [0; 4];
	let mut current_lba: [u8;8] = [0; 8];
	let mut backup_lba: [u8;8] = [0; 8];
	let mut first_usable: [u8;8] = [0; 8];
	let mut last_usable: [u8;8] = [0; 8];
	let mut disk_guid: [u8;16] = [0; 16];
	let mut start_lba: [u8; 8] = [0; 8];
	let mut num_parts: [u8; 4] = [0; 4];
	let mut part_size: [u8; 4]= [0; 4];
	let mut crc32_parts: [u8; 4] = [0; 4];

	let _ = file.read_exact(&mut revision);
	let _ = file.read_exact(&mut header_size_le);
	let _ = file.read_exact(&mut crc32);
	let _ = file.read_exact(&mut reserved);
	let _ = file.read_exact(&mut current_lba);
	let _ = file.read_exact(&mut backup_lba);
	let _ = file.read_exact(&mut first_usable);
	let _ = file.read_exact(&mut last_usable);
	let _ = file.read_exact(&mut disk_guid);
	let _ = file.read_exact(&mut start_lba);
	let _ = file.read_exact(&mut num_parts);
	let _ = file.read_exact(&mut part_size);
	let _ = file.read_exact(&mut crc32_parts);

	return Ok(Header{
		signature: signature,
		revision: revision,
		header_size_le: header_size_le,
		crc32: crc32,
		reserved: reserved,
		current_lba: current_lba,
		backup_lba: backup_lba,
		first_usable: first_usable,
		last_usable: last_usable,
		disk_guid: parse_uuid(&disk_guid)?,
		start_lba: start_lba,
		num_parts: num_parts,
		part_size: part_size,
		crc32_parts: crc32_parts
	});
}
*/
<|endoftext|>


<commit_before>// finds the longest common subsequences
// outputs the edit distance and a string containing
// all chars both inputs have in common
#[allow(non_snake_case)]
#[cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
pub fn lcs(orig: &str, edit: &str, split: &str) -> (i32, String) {

    // make list by custom splits
    let a: Vec<&str> = orig.split(split).collect();
    let b: Vec<&str> = edit.split(split).collect();

    let N = a.len() as i32;
    let M = b.len() as i32;

    let MAX = N + M;

    let mut v: Vec<i32> = (-MAX..MAX).collect();

    // container to hold common subsequence
    let mut common = String::new();

    v[1] = 0;

    // iterate over D = "edit steps"
    for D in 0..MAX {
        let mut max = 0;
        let mut max_snake: Box<String> = Box::new("".to_string());

        // TODO replace with
        // for k in (-D..D+1).step_by(2) {
        // once it's stable

        let mut k = -D;

        while k < D + 1 {
            let mut snake = String::new();

            let mut x;

            let index = (MAX + k - 1) as usize;
            if k == -D || k != D && v[index - 1] < v[index + 1] {
                x = v[index + 1];
            } else {
                x = v[index - 1] + 1;
            }

            let mut y = x - k;

            while x < N && y < M && a[x as usize] == b[y as usize] {
                if !snake.is_empty() {
                    // add back the splits that were taken away
                    snake.push_str(split);
                }
                snake.push_str(a[x as usize]);
                x += 1;
                y += 1;
            }

            v[index] = x;

            if x > max {
                max = x;
                max_snake = Box::new(snake);
            }

            if x >= N && y >= M {
                // add last max_snake
                if max_snake.len() > 0 {
                    if !common.is_empty() {
                        // add back the splits that were taken away
                        common.push_str(split);
                    }
                    common.push_str(&max_snake);
                } else {
                    common.push_str(split);
                }
                return (D, common);
            }
            k += 2;
        }

        if max_snake.len() > 0 {
            if !common.is_empty() {
                // add back the splits that were taken away
                common.push_str(split);
            }
            common.push_str(&max_snake);
        }

    }

    // both strings don't match at all
    (MAX, "".to_string())
}

#[test]
fn test_lcs() {
    assert_eq!(lcs("test", "tost", ""), (2, "tst".to_string()));
    assert_eq!(lcs("test", "test", ""), (0, "test".to_string()));

    assert_eq!(lcs("test", "test", " "), (0, "test".to_string()));

    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            "",
        ),
        (16, "The quick brown o ps over the lazy ".to_string())
    );
    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            " ",
        ),
        (6, "The quick brown over the lazy ".to_string())
    );

    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            "\n",
        ),
        (2, "".to_string())
    );
    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown fox jumps over the lazy dog",
            "\n",
        ),
        (0, "The quick brown fox jumps over the lazy dog".to_string())
    );
}
<commit_msg>Rewrite lcs()<commit_after>use std::cmp::max;

// strsplit is like `s.split(split)`, except that if `split` is "", it
// trims the leading and trailing empty elements, since the `lcs`
// logic won't handle those properly.
fn strsplit<'a>(s: &'a str, split: &str) -> Vec<&'a str> {
    let mut si = s.split(split);
    if split == "" {
        si.next();
    }
    let mut v: Vec<&str> = si.collect();
    if split == "" {
        v.pop();
    }
    v
}

// finds the longest common subsequences
// outputs the edit distance and a string containing
// all chars both inputs have in common
#[allow(non_snake_case)]
#[cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
pub fn lcs(orig: &str, edit: &str, split: &str) -> (i32, String) {
    // make list by custom splits
    let a = strsplit(orig, split);
    let b = strsplit(edit, split);

    let N = a.len();
    let M = b.len();

    let mut idx: Vec<usize> = Vec::with_capacity(N * M);
    idx.resize(N * M, 0);

    for i in 0..N {
        for j in 0..M {
            if b[j] == a[i] {
                if i == 0 || j == 0 {
                    idx[i * M + j] = 1;
                } else {
                    idx[i * M + j] = idx[(i - 1) * M + j - 1] + 1;
                }
            } else if i == 0 {
                if j == 0 {
                    idx[i * M + j] = 0;
                } else {
                    idx[i * M + j] = idx[i * M + j - 1];
                }
            } else if j == 0 {
                idx[i * M + j] = idx[(i - 1) * M + j];
            } else {
                idx[i * M + j] = max(idx[i * M + j - 1], idx[(i - 1) * M + j]);
            }
        }
    }

    let mut i = (N as isize) - 1;
    let mut j = (M as isize) - 1;
    let mut lcs = Vec::new();
    while i >= 0 && j >= 0 {
        let ui = i as usize;
        let uj = j as usize;
        if a[ui] == b[uj] {
            lcs.push(a[ui]);
            i -= 1;
            j -= 1;
        } else if j == 0 && i == 0 {
            break;
        } else if i == 0 || idx[ui * M + uj - 1] > idx[(ui - 1) * M + uj] {
            j -= 1;
        } else {
            i -= 1;
        }
    }

    lcs.reverse();
    ((N + M - 2 * lcs.len()) as i32, lcs.join(split))
}

#[test]
fn test_lcs() {
    assert_eq!(lcs("test", "tost", ""), (2, "tst".to_string()));
    assert_eq!(lcs("test", "test", ""), (0, "test".to_string()));

    assert_eq!(lcs("test", "test", " "), (0, "test".to_string()));

    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            "",
        ),
        (16, "The quick brown o ps over the lazy ".to_string())
    );
    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            " ",
        ),
        (6, "The quick brown over the lazy".to_string())
    );

    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            "\n",
        ),
        (2, "".to_string())
    );
    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown fox jumps over the lazy dog",
            "\n",
        ),
        (0, "The quick brown fox jumps over the lazy dog".to_string())
    );

    assert_eq!(
        lcs("a b : c", "b a : b : c", " "),
        (2, "a b : c".to_string())
    );

    assert_eq!(lcs("", "a b c", ""), (5, "".to_string()));

    assert_eq!(lcs("", " a", " "), (1, "".to_string()));
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

#![warn(missing_copy_implementations)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![deny(warnings)]

#![cfg_attr(feature="cargo-clippy", warn(cast_possible_truncation))]
#![cfg_attr(feature="cargo-clippy", warn(cast_possible_wrap))]
#![cfg_attr(feature="cargo-clippy", warn(cast_precision_loss))]
#![cfg_attr(feature="cargo-clippy", warn(cast_sign_loss))]
#![cfg_attr(feature="cargo-clippy", warn(enum_glob_use))]
#![cfg_attr(feature="cargo-clippy", warn(mut_mut))]
#![cfg_attr(feature="cargo-clippy", warn(mutex_integer))]
#![cfg_attr(feature="cargo-clippy", warn(non_ascii_literal))]
#![cfg_attr(feature="cargo-clippy", warn(nonminimal_bool))]
#![cfg_attr(feature="cargo-clippy", warn(option_unwrap_used))]
#![cfg_attr(feature="cargo-clippy", warn(result_unwrap_used))]
#![cfg_attr(feature="cargo-clippy", warn(single_match_else))]
#![cfg_attr(feature="cargo-clippy", warn(string_add))]
#![cfg_attr(feature="cargo-clippy", warn(string_add_assign))]
#![cfg_attr(feature="cargo-clippy", warn(unicode_not_nfc))]
#![cfg_attr(feature="cargo-clippy", warn(wrong_pub_self_convention))]

//! Message Passing Interface bindings for Rust
//!
//! The [Message Passing Interface][MPI] (MPI) is a specification for a
//! message-passing style concurrency library. Implementations of MPI are often used to structure
//! parallel computation on High Performance Computing systems. The MPI specification describes
//! bindings for the C programming language (and through it C++) as well as for the Fortran
//! programming language. This library tries to bridge the gap into a more rustic world.
//!
//! [MPI]: http://www.mpi-forum.org
//!
//! # Usage
//!
//! Add the `mpi` crate as a dependency in your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! mpi = { git = "https://github.com/bsteinb/rsmpi.git", tag = "0.4.0" }
//! ```
//!
//! Then use it in your program like this:
//!
//! ```no_run
//! extern crate mpi;
//!
//! use mpi::traits::*;
//!
//! fn main() {
//!     let universe = mpi::initialize().unwrap();
//!     let world = universe.world();
//!     let size = world.size();
//!     let rank = world.rank();
//!
//!     if size != 2 {
//!         panic!("Size of MPI_COMM_WORLD must be 2, but is {}!", size);
//!      }
//!
//!     match rank {
//!         0 => {
//!             let msg = vec![4.0f64, 8.0, 15.0];
//!             world.process_at_rank(rank + 1).send(&msg[..]);
//!         }
//!         1 => {
//!             let (msg, status) = world.any_process().receive_vec::<f64>();
//!             println!("Process {} got message {:?}.\nStatus is: {:?}", rank, msg, status);
//!         }
//!         _ => unreachable!()
//!     }
//! }
//! ```
//!
//! # Features
//!
//! The bindings follow the MPI 3.1 specification.
//!
//! Currently supported:
//!
//! - **Groups, Contexts, Communicators**:
//!   - Group and (Intra-)Communicator management from section 6 is mostly complete.
//!   - no Inter-Communicators
//!   - no process topologies
//! - **Point to point communication**:
//!   - standard, buffered, synchronous and ready mode send in blocking and non-blocking variants
//!   - receive in blocking and non-blocking variants
//!   - send-receive
//!   - probe
//!   - matched probe/receive
//! - **Collective communication**:
//!   - barrier
//!   - broadcast
//!   - (all) gather
//!   - scatter
//!   - all to all
//!   - varying counts operations
//!   - reductions/scans
//!   - blocking and non-blocking variants
//! - **Datatypes**: Bridging between Rust types and MPI basic types as well as custom MPI datatypes
//! which can act as views into buffers.
//!
//! Not supported (yet):
//!
//! - Process management
//! - One-sided communication (RMA)
//! - MPI parallel I/O
//! - A million small things
//!
//! The sub-modules contain a more detailed description of which features are and are not
//! supported.
//!
//! # Further Reading
//!
//! While every publicly defined item in this crate should have some documentation attached to it,
//! most of the descriptions are quite terse for now and to the uninitiated will only make sense in
//! combination with the [MPI specification][MPIspec].
//!
//! [MPIspec]: http://www.mpi-forum.org/docs/docs.html

use std::os::raw::c_int;

extern crate conv;
extern crate libffi;

/// The raw C language MPI API
///
/// Documented in the [Message Passing Interface specification][spec]
///
/// [spec]: http://www.mpi-forum.org/docs/docs.html
#[allow(missing_docs, dead_code, non_snake_case, non_camel_case_types)]
#[macro_use]
pub mod ffi;

pub mod collective;
pub mod datatype;
pub mod environment;
pub mod point_to_point;
pub mod raw;
pub mod request;
pub mod topology;

/// Re-exports all traits.
pub mod traits {
    pub use collective::traits::*;
    pub use datatype::traits::*;
    pub use point_to_point::traits::*;
    pub use raw::traits::*;
    pub use topology::traits::*;
}

#[doc(inline)]
pub use environment::{initialize, initialize_with_threading, Threading, time, time_resolution};

use ffi::MPI_Aint;

/// Encodes error values returned by MPI functions.
pub type Error = c_int;
/// Encodes number of values in multi-value messages.
pub type Count = c_int;
/// Can be used to tag messages on the sender side and match on the receiver side.
pub type Tag = c_int;
/// An address in memory
pub type Address = MPI_Aint;
<commit_msg>update usage instructions in crate documentation<commit_after>#![deny(missing_docs)]

#![warn(missing_copy_implementations)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![deny(warnings)]

#![cfg_attr(feature="cargo-clippy", warn(cast_possible_truncation))]
#![cfg_attr(feature="cargo-clippy", warn(cast_possible_wrap))]
#![cfg_attr(feature="cargo-clippy", warn(cast_precision_loss))]
#![cfg_attr(feature="cargo-clippy", warn(cast_sign_loss))]
#![cfg_attr(feature="cargo-clippy", warn(enum_glob_use))]
#![cfg_attr(feature="cargo-clippy", warn(mut_mut))]
#![cfg_attr(feature="cargo-clippy", warn(mutex_integer))]
#![cfg_attr(feature="cargo-clippy", warn(non_ascii_literal))]
#![cfg_attr(feature="cargo-clippy", warn(nonminimal_bool))]
#![cfg_attr(feature="cargo-clippy", warn(option_unwrap_used))]
#![cfg_attr(feature="cargo-clippy", warn(result_unwrap_used))]
#![cfg_attr(feature="cargo-clippy", warn(single_match_else))]
#![cfg_attr(feature="cargo-clippy", warn(string_add))]
#![cfg_attr(feature="cargo-clippy", warn(string_add_assign))]
#![cfg_attr(feature="cargo-clippy", warn(unicode_not_nfc))]
#![cfg_attr(feature="cargo-clippy", warn(wrong_pub_self_convention))]

//! Message Passing Interface bindings for Rust
//!
//! The [Message Passing Interface][MPI] (MPI) is a specification for a
//! message-passing style concurrency library. Implementations of MPI are often used to structure
//! parallel computation on High Performance Computing systems. The MPI specification describes
//! bindings for the C programming language (and through it C++) as well as for the Fortran
//! programming language. This library tries to bridge the gap into a more rustic world.
//!
//! [MPI]: http://www.mpi-forum.org
//!
//! # Usage
//!
//! Add the `mpi` crate as a dependency in your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! mpi = "0.5"
//! ```
//!
//! Then use it in your program like this:
//!
//! ```no_run
//! extern crate mpi;
//!
//! use mpi::traits::*;
//!
//! fn main() {
//!     let universe = mpi::initialize().unwrap();
//!     let world = universe.world();
//!     let size = world.size();
//!     let rank = world.rank();
//!
//!     if size != 2 {
//!         panic!("Size of MPI_COMM_WORLD must be 2, but is {}!", size);
//!      }
//!
//!     match rank {
//!         0 => {
//!             let msg = vec![4.0f64, 8.0, 15.0];
//!             world.process_at_rank(rank + 1).send(&msg[..]);
//!         }
//!         1 => {
//!             let (msg, status) = world.any_process().receive_vec::<f64>();
//!             println!("Process {} got message {:?}.\nStatus is: {:?}", rank, msg, status);
//!         }
//!         _ => unreachable!()
//!     }
//! }
//! ```
//!
//! # Features
//!
//! The bindings follow the MPI 3.1 specification.
//!
//! Currently supported:
//!
//! - **Groups, Contexts, Communicators**:
//!   - Group and (Intra-)Communicator management from section 6 is mostly complete.
//!   - no Inter-Communicators
//!   - no process topologies
//! - **Point to point communication**:
//!   - standard, buffered, synchronous and ready mode send in blocking and non-blocking variants
//!   - receive in blocking and non-blocking variants
//!   - send-receive
//!   - probe
//!   - matched probe/receive
//! - **Collective communication**:
//!   - barrier
//!   - broadcast
//!   - (all) gather
//!   - scatter
//!   - all to all
//!   - varying counts operations
//!   - reductions/scans
//!   - blocking and non-blocking variants
//! - **Datatypes**: Bridging between Rust types and MPI basic types as well as custom MPI datatypes
//! which can act as views into buffers.
//!
//! Not supported (yet):
//!
//! - Process management
//! - One-sided communication (RMA)
//! - MPI parallel I/O
//! - A million small things
//!
//! The sub-modules contain a more detailed description of which features are and are not
//! supported.
//!
//! # Further Reading
//!
//! While every publicly defined item in this crate should have some documentation attached to it,
//! most of the descriptions are quite terse for now and to the uninitiated will only make sense in
//! combination with the [MPI specification][MPIspec].
//!
//! [MPIspec]: http://www.mpi-forum.org/docs/docs.html

use std::os::raw::c_int;

extern crate conv;
extern crate libffi;

/// The raw C language MPI API
///
/// Documented in the [Message Passing Interface specification][spec]
///
/// [spec]: http://www.mpi-forum.org/docs/docs.html
#[allow(missing_docs, dead_code, non_snake_case, non_camel_case_types)]
#[macro_use]
pub mod ffi;

pub mod collective;
pub mod datatype;
pub mod environment;
pub mod point_to_point;
pub mod raw;
pub mod request;
pub mod topology;

/// Re-exports all traits.
pub mod traits {
    pub use collective::traits::*;
    pub use datatype::traits::*;
    pub use point_to_point::traits::*;
    pub use raw::traits::*;
    pub use topology::traits::*;
}

#[doc(inline)]
pub use environment::{initialize, initialize_with_threading, Threading, time, time_resolution};

use ffi::MPI_Aint;

/// Encodes error values returned by MPI functions.
pub type Error = c_int;
/// Encodes number of values in multi-value messages.
pub type Count = c_int;
/// Can be used to tag messages on the sender side and match on the receiver side.
pub type Tag = c_int;
/// An address in memory
pub type Address = MPI_Aint;
<|endoftext|>