#![no_std] // const WIDTH: u16 = 64; // const HEIGHT: u16 = 32; // const PIXELS: usize = (WIDTH * HEIGHT) as usize; // const FONT: [u8; 80] = [ // 0xF0, 0x90, 0x90, 0x90, 0xF0, //0 // 0x20, 0x60, 0x20, 0x20, 0x70, //1 // 0xF0, 0x10, 0xF0, 0x80, 0xF0, //2 // 0xF0, 0x10, 0xF0, 0x10, 0xF0, //3 // 0x90, 0x90, 0xF0, 0x10, 0x10, //4 // 0xF0, 0x80, 0xF0, 0x10, 0xF0, //5 // 0xF0, 0x80, 0xF0, 0x90, 0xF0, //6 // 0xF0, 0x10, 0x20, 0x40, 0x40, //7 // 0xF0, 0x90, 0xF0, 0x90, 0xF0, //8 // 0xF0, 0x90, 0xF0, 0x10, 0xF0, //9 // 0xF0, 0x90, 0xF0, 0x90, 0x90, //A // 0xE0, 0x90, 0xE0, 0x90, 0xE0, //B // 0xF0, 0x80, 0x80, 0x80, 0xF0, //C // 0xE0, 0x90, 0x90, 0x90, 0xE0, //D // 0xF0, 0x80, 0xF0, 0x80, 0xF0, //E // 0xF0, 0x80, 0xF0, 0x80, 0x80, //F // ]; // fn unknown_opcode(opcode: u16) { // eprintln!("Unknwown opcode {:#06x}", opcode); // std::process::exit(1); // } // struct RandomGenerator { // random: u8, // } // impl RandomGenerator { // fn new() -> Self { // Self { random: 92 } // } // } // impl Iterator for RandomGenerator { // type Item = u8; // fn next(&mut self) -> Option { // self.random ^= self.random << 6; // self.random ^= self.random >> 4; // self.random ^= self.random << 1; // Some(self.random) // } // } // pub struct Chip8 { // v: [u8; 16], // i: u16, // pc: u16, // stack: [u16; 16], // sp: u16, // memory: [u8; 4096], // screen: [u8; PIXELS], // delay_timer: u8, // sound_timer: u8, // key: [u8; 16], // draw: bool, // random: RandomGenerator, // } // impl Chip8 { // pub fn new() -> Self { // let mut r = Self { // v: [0; 16], // i: 0, // pc: 0x200, // stack: [0; 16], // sp: 0, // memory: [0; 4096], // screen: [0; PIXELS], // delay_timer: 0, // sound_timer: 0, // key: [0; 16], // draw: false, // random: RandomGenerator::new(), // }; // r.memory[..80].copy_from_slice(&FONT); // r // } // pub fn load_rom(&mut self, mut reader: R) -> std::io::Result<()> { // reader.read(&mut self.memory[0x200..])?; // Ok(()) // } // pub fn cycle(&mut self) { // let pc = self.pc as usize; // let opcode = ((self.memory[pc] as u16) << 8) | self.memory[pc + 1] as u16; // let x = ((opcode & 0x0F00) >> 8) as usize; // let y = ((opcode & 0x00F0) >> 4) as usize; // let n = opcode & 0x000F; // let nn = (opcode & 0x00FF) as u8; // let nnn = opcode & 0x0FFF; // self.pc += 2; // match opcode & 0xF000 { // 0x0000 => match opcode & 0x000F { // 0x0000 => { // eprintln!("CLS"); // self.screen = [0; PIXELS]; // self.draw = true; // } // 0x000E => { // eprintln!("RET"); // self.sp -= 1; // self.pc = self.stack[self.sp as usize]; // } // _ => unknown_opcode(opcode), // }, // 0x1000 => { // eprintln!("JP {}", nnn); // self.pc = nnn; // } // 0x2000 => { // eprintln!("CALL {}", nnn); // self.stack[self.sp as usize] = self.pc; // self.sp += 1; // self.pc = nnn; // } // 0x3000 => { // eprintln!("SE V{}, {}", x, nn); // if self.v[x] == nn { // self.pc += 2; // } // } // 0x4000 => { // eprintln!("SNE V{}, {}", x, nn); // if self.v[x] != nn { // self.pc += 2; // } // } // 0x5000 => { // eprintln!("SE V{}, V{}", x, y); // if self.v[x] == self.v[y] { // self.pc += 2; // } // } // 0x6000 => { // eprintln!("LD V{}, {}", x, nn); // self.v[x] = nn; // } // 0x7000 => { // eprintln!("ADD V{}, {}", x, nn); // self.v[x] = self.v[x].wrapping_add(nn); // } // 0x8000 => match opcode & 0x000F { // 0x0000 => { // eprintln!("LD V{}, V{}", x, y); // self.v[x] = self.v[y]; // } // 0x0001 => { // eprintln!("OR V{}, V{}", x, y); // self.v[x] |= self.v[y]; // } // 0x0002 => { // eprintln!("AND V{}, V{}", x, y); // self.v[x] &= self.v[y]; // } // 0x0003 => { // eprintln!("XOR V{}, V{}", x, y); // self.v[x] ^= self.v[y]; // } // 0x0004 => { // eprintln!("ADD V{}, V{}", x, y); // let vx = self.v[x] as u16; // let vy = self.v[y] as u16; // let v = vx + vy; // self.v[0xF] = if v > 255 { 1 } else { 0 }; // self.v[x] = v as u8; // } // 0x0005 => { // eprintln!("SUB V{}, V{}", x, y); // self.v[0xF] = if self.v[x] > self.v[y] { 1 } else { 0 }; // self.v[x] = self.v[x].wrapping_sub(self.v[y]); // } // 0x0006 => { // eprintln!("SHR V{}", x); // self.v[0xF] = if self.v[x] & 1 == 1 { 1 } else { 0 }; // self.v[x] /= 2; // } // 0x0007 => { // eprintln!("SUBN V{}, V{}", x, y); // self.v[0xF] = if self.v[y] > self.v[x] { 1 } else { 0 }; // self.v[x] = self.v[y].wrapping_sub(self.v[x]); // } // 0x000E => { // eprintln!("SHL V{}", x); // self.v[0xF] = if (self.v[x] >> 7) & 1 == 1 { 1 } else { 0 }; // self.v[x] = self.v[x].wrapping_mul(2); // } // _ => unknown_opcode(opcode), // }, // 0x9000 => { // eprintln!("SNE V{}, V{}", x, y); // if self.v[x] != self.v[y] { // self.pc += 2; // } // } // 0xA000 => { // eprintln!("LD I, {}", nnn); // self.i = nnn; // } // 0xC000 => { // eprintln!("RND V{}, {}", x, nn); // self.v[x] = self.random.next().unwrap_or(0) & nn; // } // 0xD000 => { // eprintln!("DRW V{}, V{}, {}", x, y, n); // let vx = self.v[x] as u16; // let vy = self.v[y] as u16; // self.v[0xF] = 0; // for yy in 0..n { // let pixel = self.memory[(self.i + yy) as usize]; // for xx in 0..8 { // if (pixel & (0x80 >> xx)) != 0 { // let si = vx + xx + ((vy + yy) * WIDTH); // if self.screen[si as usize] == 1 { // self.v[0xF] = 1; // } // self.screen[si as usize] ^= 1; // } // } // } // self.draw = true; // } // 0xE000 => match opcode & 0x00FF { // 0x009E => { // eprintln!("SKP V{}", x); // if self.key[self.v[x] as usize] == 1 { // self.pc += 2; // } // } // 0x00A1 => { // eprintln!("SKNP V{}", x); // if self.key[self.v[x] as usize] == 0 { // self.pc += 2; // } // } // _ => unknown_opcode(opcode), // }, // 0xF000 => match opcode & 0x00FF { // 0x0007 => { // eprintln!("LD V{}, DT", x); // self.v[x] = self.delay_timer; // } // 0x0015 => { // eprintln!("LD DT, V{}", x); // self.delay_timer = self.v[x]; // } // 0x0018 => { // eprintln!("LD ST, V{}", x); // self.sound_timer = self.v[x]; // } // 0x001E => { // eprintln!("ADD, I, V{}", x); // self.i += self.v[x] as u16; // } // 0x0029 => { // eprintln!("LD F, V{}", x); // self.i = x as u16 * 5; // } // 0x0033 => { // eprintln!("LD, B, V{}", x); // let i = self.i as usize; // self.memory[i] = self.v[x] / 100; // self.memory[i + 1] = (self.v[x] / 10) % 10; // self.memory[i + 2] = (self.v[x] % 100) % 10; // } // 0x0055 => { // eprintln!("LD [I], V{}", x); // let i = self.i as usize; // self.memory[i..=i + x].copy_from_slice(&self.v[..=x]); // } // 0x0065 => { // eprintln!("LD V{}, [I]", x); // let i = self.i as usize; // self.v[..=x].copy_from_slice(&self.memory[i..=i + x]); // } // _ => unknown_opcode(opcode), // }, // _ => unknown_opcode(opcode), // }; // if self.delay_timer > 0 { // self.delay_timer -= 1; // } // if self.sound_timer > 0 { // if self.sound_timer == 1 { // eprintln!("BEEP"); // } // self.sound_timer -= 1; // } // } // pub fn display(&mut self) -> std::io::Result<()> { // if self.draw { // self.draw = false; // self.draw() // } else { // Ok(()) // } // } // fn draw(&self) -> std::io::Result<()> { // let stdout = std::io::stdout(); // let mut handle = stdout.lock(); // handle.write_all(b"\x1B[2J\n")?; // for y in 0..HEIGHT { // for x in 0..WIDTH { // let si = x + y * WIDTH; // let buf = if self.screen[si as usize] == 0 { // "░".as_bytes() // } else { // "█".as_bytes() // }; // handle.write_all(buf)?; // } // handle.write_all(b"\n")?; // } // handle.flush() // } // }