pub struct InstructionUtil {} impl InstructionUtil { /// Byte To Bools /// Convert a u8 byte to an array of bool pub fn byte_to_bools(to_convert: u8) -> [bool; 8] { let mut return_values = [false; 8]; for i in 0..8 { let new_value = to_convert >> i & 0x1 == 1; return_values[i as usize] = new_value; } return_values } /// Byte To Bools /// Convert an array of bool to a u8 pub fn bools_to_byte(to_convert: [bool; 8]) -> u8 { let mut return_value = 0u8; for i in 0..to_convert.len() { let new_bit = 0x1 << i; if to_convert[i] { return_value |= new_bit } } return_value } /// Split Bytes /// Split a u16 into a pair of u8 values for high and low byte pub fn split_bytes(to_split: u16) -> (u8, u8) { let high = to_split.rotate_left(8) as u8; let low = (to_split & 0xff) as u8; (high, low) } /// Join Bytes /// Joins 2 u8 into a single u16 with high and low /// bytes provided pub fn join_bytes(high: u8, low: u8) -> u16 { (high as u16) << 8 | low as u16 } /// Swap Endian /// Swaps the endianess of a value /// 0xabcd -> 0xcdab pub fn swap_endian(to_swap:u16) -> u16 { let low = to_swap & 0xff; let high = to_swap & 0xff00; low << 8 | high >> 8 } /// Split Bytes Swap Endian /// Swaps endianness and return both bytes separately pub fn split_bytes_swap_endian(to_split: u16) -> (u8, u8) { InstructionUtil::split_bytes(InstructionUtil::swap_endian(to_split)) } /// Join Bytes Swap Endian /// Swaps endianness and returns the combined bytes pub fn join_bytes_swap_endian(high :u8, low: u8) -> u16 { InstructionUtil::swap_endian(InstructionUtil::join_bytes(high, low)) } /// Read Address from Instruction /// Reads the 'address' portion of an instruction /// Returns the 12 LSB /// 0xabcd -> 0x0bcd pub fn read_addr_from_instruction(instruction_to_read_from: u16) -> u16 { instruction_to_read_from & 0x0FFF } /// Read Nibble from Instruction /// Returns the lowest 4 bits of the instruction /// 0xabcd -> 0x0d pub fn read_nibble_from_instruction(instruction_to_read_from: u16) -> u8 { ( instruction_to_read_from & 0x000F )as u8 } /// Read X From Instruction /// Returns the 4 LSB of the high byte of the instruction /// Returns bits 9-13 /// 0xabcd -> 0x0b pub fn read_x_from_instruction(instruction_to_read_from: u16) -> u8 { (instruction_to_read_from & 0x0F00).rotate_right(8) as u8 } /// Read Y from Instruction /// Returns the 4 MSB from the low byte of the instruction /// Returns bits 5-8 /// 0xabcd -> 0x0c pub fn read_y_from_instruction(instruction_to_read_from: u16) -> u8 { (instruction_to_read_from & 0x00F0).rotate_right(4) as u8 } /// Read Byte from Instruction /// Returns the 8 LSB from the instruction /// Returns bits 0-7 /// 0xabcd -> 0xcd pub fn read_byte_from_instruction(instruction_to_read_from: u16) -> u8 { (instruction_to_read_from & 0x00FF) as u8 } /// Alias for read_x_from_instruction pub fn read_upper_byte_lower_nibble(to_read_from: u16) -> u8 { InstructionUtil::read_x_from_instruction(to_read_from) } pub fn read_bits_from_instruction(instruction_bytes: u16, first_bit: u8, last_bit: u8) -> u16 { // shift the value over by the 'first bit' bits let working = instruction_bytes.rotate_right(first_bit as u32); let mut working_mask: i32 = 0x00; // build the mask for _ in first_bit..=last_bit { working_mask = working_mask.rotate_left(1) | 0x01; } // apply the mask to the working value working & working_mask as u16 } }