diff options
| author | Samuel Perrouault <samuel.perrouault@gmail.com> | 2025-07-23 00:05:12 +0200 |
|---|---|---|
| committer | Samuel Perrouault <samuel.perrouault@gmail.com> | 2025-07-23 00:05:12 +0200 |
| commit | f03fa6fa77a68bff80b65ee69765042076a306c2 (patch) | |
| tree | 6bbc1ef9ac4efb5f1a8f7f8c3994600069428856 /src | |
| parent | ab5177eff4b938f080c67a524165462a56d0d352 (diff) | |
exploring a fully static pathstatic_exe
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 627 | ||||
| -rw-r--r-- | src/main.rs | 130 |
2 files changed, 416 insertions, 341 deletions
@@ -1,328 +1,327 @@ -use std::io::Read; -use std::io::Write; +#![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 -]; +// 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); -} +// fn unknown_opcode(opcode: u16) { +// eprintln!("Unknwown opcode {:#06x}", opcode); +// std::process::exit(1); +// } -struct RandomGenerator { - random: u8, -} +// struct RandomGenerator { +// random: u8, +// } -impl RandomGenerator { - fn new() -> Self { - Self { random: 92 } - } -} +// impl RandomGenerator { +// fn new() -> Self { +// Self { random: 92 } +// } +// } -impl Iterator for RandomGenerator { - type Item = u8; +// impl Iterator for RandomGenerator { +// type Item = u8; - fn next(&mut self) -> Option<Self::Item> { - self.random ^= self.random << 6; - self.random ^= self.random >> 4; - self.random ^= self.random << 1; - Some(self.random) - } -} +// fn next(&mut self) -> Option<Self::Item> { +// 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, -} +// 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 - } +// 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<R: Read>(&mut self, mut reader: R) -> std::io::Result<()> { - reader.read(&mut self.memory[0x200..])?; - Ok(()) - } +// pub fn load_rom<R: Read>(&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), - }; +// 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.delay_timer > 0 { +// self.delay_timer -= 1; +// } - if self.sound_timer > 0 { - if self.sound_timer == 1 { - eprintln!("BEEP"); - } - self.sound_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(()) - } - } +// 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() - } -} +// 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() +// } +// } diff --git a/src/main.rs b/src/main.rs index bb0ae71..5f977ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,31 +1,107 @@ -use std::{ - fs::File, - io::BufReader, - time::{Duration, Instant}, -}; - -const SECOND: u64 = 1_000_000_000; -const REFRESH_RATE: u64 = 60; -const FRAME_DURATION: Duration = Duration::from_nanos(SECOND / REFRESH_RATE); - -fn main() -> std::io::Result<()> { - if let Some(arg) = std::env::args().nth(1) { - let mut chip8 = chip8::Chip8::new(); - { - let file = File::open(arg)?; - let buf_reader = BufReader::new(file); - chip8.load_rom(buf_reader)?; +#![no_std] +#![no_main] + +use core::fmt::Write; + +#[cfg(target_arch = "x86_64")] +core::arch::global_asm!( + ".text", + ".global _start", + ".type _start,@function", + "_start:", + "xor rbp,rbp", + "mov rdi, rsp", + ".weak _DYNAMIC", + ".hidden _DYNAMIC", + "lea rsi, [rip + _DYNAMIC]", + "and rsp,-16", + "call __proxy_main" +); + +struct Printer { + buf: [u8; 512], + pos: usize, +} + +impl Printer { + fn new() -> Self { + Self { + buf: [0; 512], + pos: 0, } - loop { - let start = Instant::now(); - for _ in 0..8 { - chip8.cycle(); - } - chip8.display()?; - std::thread::sleep(FRAME_DURATION - start.elapsed()); + } + + fn bytes(&self) -> &[u8] { + &self.buf[..self.pos] + } +} + +impl core::fmt::Write for Printer { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + let remaining_buf = &mut self.buf[self.pos..]; + let raw_s = s.as_bytes(); + let write_num = raw_s.len().min(remaining_buf.len()); + remaining_buf[..write_num].copy_from_slice(&raw_s[..write_num]); + self.pos += raw_s.len(); + if write_num < raw_s.len() { + Err(core::fmt::Error) + } else { + Ok(()) } - } else { - println!("usage: chip8 rompath") } - Ok(()) } + +#[panic_handler] +fn panic(info: &core::panic::PanicInfo) -> ! { + let mut p = Printer::new(); + let _ = write!(&mut p, "Fatal error: {}\n", info); + let stderr = unsafe { rustix::stdio::stderr() }; + let _ = rustix::io::write(stderr, p.bytes()); + rustix::runtime::exit_group(1) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn __proxy_main(_stack_ptr: *const u8, _dynv: *const usize) { + let code = main(); + rustix::runtime::exit_group(code); +} + +fn main() -> i32 { + let mut p = Printer::new(); + write!(&mut p, "Hello {}, you are worth {} tons of gold\n", "Jacques", 10_000).expect("Could not format this"); + let stdout = unsafe { rustix::stdio::stdout() }; + let _ = rustix::io::write(stdout, p.bytes()); + 0 +} + +// use std::{ +// fs::File, +// io::BufReader, +// time::{Duration, Instant}, +// }; + +// const SECOND: u64 = 1_000_000_000; +// const REFRESH_RATE: u64 = 60; +// const FRAME_DURATION: Duration = Duration::from_nanos(SECOND / REFRESH_RATE); + +// fn main() -> std::io::Result<()> { +// if let Some(arg) = std::env::args().nth(1) { +// let mut chip8 = chip8::Chip8::new(); +// { +// let file = File::open(arg)?; +// let buf_reader = BufReader::new(file); +// chip8.load_rom(buf_reader)?; +// } +// loop { +// let start = Instant::now(); +// for _ in 0..8 { +// chip8.cycle(); +// } +// chip8.display()?; +// std::thread::sleep(FRAME_DURATION - start.elapsed()); +// } +// } else { +// println!("usage: chip8 rompath") +// } +// Ok(()) +// } |
