3XLBOYDI3OAFVKURUK3HWBLLRFWTCTWZDR4RT33C73YFWGYTMRPQC use c8::{Chip8, Display, KeyCode, HEIGHT, WIDTH};use minifb::{Key, Scale, Window, WindowOptions};use std::{sync::{mpsc::Sender, Arc},thread,time::Duration,};fn main() {// let program = include_bytes!("roms/IBM_Logo.ch8");// let program = include_bytes!("roms/bc_test.ch8");// let program = include_bytes!("roms/test_opcode.ch8");// let program = include_bytes!("roms/octojam2title.ch8");// let program = include_bytes!("roms/octojam3title.ch8");// let program = include_bytes!("roms/1dcell.ch8");// let program = include_bytes!("roms/snek.ch8");// let program = include_bytes!("roms/br8kout.ch8");// let program = include_bytes!("roms/4-flags.ch8");// let program = include_bytes!("roms/3-corax+.ch8");// let program = include_bytes!("roms/5-quirks.ch8");let program = include_bytes!("roms/6-keypad.ch8");let mut c8 = Chip8::new(program);run::<700>(&mut c8);}pub enum Event {Key(KeyCode),Timer,Tick,}pub fn run<const F: u64>(c8: &mut Chip8) {let (tx, rx) = std::sync::mpsc::channel();let tx1 = tx.clone();thread::spawn(move || {let millis = 1000000 / 60;let int = Duration::from_micros(millis);loop {thread::sleep(int);tx1.send(Event::Timer).unwrap();}});let tx2 = tx.clone();thread::spawn(move || {let millis = 1000000 / F;let int = Duration::from_micros(millis);loop {thread::sleep(int);tx2.send(Event::Tick).unwrap();}});show_display(c8.display.clone(), Some(tx));loop {c8.step();let event = rx.recv().unwrap();match event {Event::Key(k) => c8.set_key_pressed(k),Event::Timer => c8.decr_timers(),Event::Tick => {}}}}pub fn show_display(display: Arc<Display>, sender: Option<Sender<Event>>) {struct Input {sender: Sender<Event>,}impl Input {fn new(sender: Sender<Event>) -> Input {Input { sender }}}impl minifb::InputCallback for Input {fn add_char(&mut self, uni_char: u32) {if let Some(c) = char::from_u32(uni_char) {if let Ok(key) = c.try_into() {self.sender.send(Event::Key(key)).unwrap();}}}}std::thread::spawn(move || {let mut window = Window::new("Chip8",WIDTH,HEIGHT,WindowOptions {scale: Scale::X16,..WindowOptions::default()},).unwrap_or_else(|e| {panic!("{}", e);});// Limit to max ~60 fps update ratewindow.limit_update_rate(Some(std::time::Duration::from_micros(16600)));if let Some(sender) = sender {let input = Box::new(Input::new(sender));// Limit to max ~60 fps update ratewindow.set_input_callback(input);}while window.is_open() && !window.is_key_down(Key::Escape) {// We unwrap here as we want this code to exit if it fails. Real applications may want to handle this in a different waywindow.update_with_buffer(display.get_buffer(), WIDTH, HEIGHT).unwrap();}});}
use core::panic;use std::{cell::UnsafeCell, mem, sync::Arc};static NUMBER_FONT: [u8; 5 * 16] = [0xF0, 0x90, 0x90, 0x90, 0xF0, // 00x20, 0x60, 0x20, 0x20, 0x70, // 10xF0, 0x10, 0xF0, 0x80, 0xF0, // 20xF0, 0x10, 0xF0, 0x10, 0xF0, // 30x90, 0x90, 0xF0, 0x10, 0x10, // 40xF0, 0x80, 0xF0, 0x10, 0xF0, // 50xF0, 0x80, 0xF0, 0x90, 0xF0, // 60xF0, 0x10, 0x20, 0x40, 0x40, // 70xF0, 0x90, 0xF0, 0x90, 0xF0, // 80xF0, 0x90, 0xF0, 0x10, 0xF0, // 90xF0, 0x90, 0xF0, 0x90, 0x90, // A0xE0, 0x90, 0xE0, 0x90, 0xE0, // B0xF0, 0x80, 0x80, 0x80, 0xF0, // C0xE0, 0x90, 0x90, 0x90, 0xE0, // D0xF0, 0x80, 0xF0, 0x80, 0xF0, // E0xF0, 0x80, 0xF0, 0x80, 0x80, // F];#[derive(Debug, Clone, Copy)]#[repr(u8)]pub enum KeyCode {Zero,One,Two,Three,Four,Five,Six,Seven,Height,Nine,A,B,C,D,E,F,}impl core::fmt::Display for KeyCode {fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {match *self {KeyCode::Zero => f.write_str("0"),KeyCode::One => f.write_str("1"),KeyCode::Two => f.write_str("2"),KeyCode::Three => f.write_str("3"),KeyCode::Four => f.write_str("4"),KeyCode::Five => f.write_str("5"),KeyCode::Six => f.write_str("6"),KeyCode::Seven => f.write_str("7"),KeyCode::Height => f.write_str("8"),KeyCode::Nine => f.write_str("9"),KeyCode::A => f.write_str("A"),KeyCode::B => f.write_str("B"),KeyCode::C => f.write_str("C"),KeyCode::D => f.write_str("D"),KeyCode::E => f.write_str("E"),KeyCode::F => f.write_str("F"),}}}impl KeyCode {pub fn to_u8(&self) -> u8 {let val = unsafe { mem::transmute_copy(self) };// println!("{self}={val}");val}}impl TryFrom<char> for KeyCode {type Error = ();fn try_from(value: char) -> Result<Self, Self::Error> {Ok(match value {'&' => KeyCode::One,'é' => KeyCode::Two,'"' => KeyCode::Three,'\'' => KeyCode::C,'a' => KeyCode::Four,'z' => KeyCode::Five,'e' => KeyCode::Six,'r' => KeyCode::D,'q' => KeyCode::Seven,'s' => KeyCode::Height,'d' => KeyCode::Nine,'f' => KeyCode::E,'w' => KeyCode::A,'x' => KeyCode::Zero,'c' => KeyCode::B,'v' => KeyCode::F,_ => return Err(()),})}}struct Memory {buf: [u8; 4096],}impl Memory {fn new() -> Self {Memory { buf: [0; 4096] }}fn load_at(&mut self, at: u16, bytes: &[u8]) {let start = at as usize;let end = start + bytes.len();// println!("{bytes:x?}");self.buf[start..end].copy_from_slice(bytes);}fn read(&self, at: u16) -> u8 {self.buf[at as usize]}fn write(&mut self, at: u16, val: u8) {self.buf[at as usize] = val;}}pub const WIDTH: usize = 64;pub const HEIGHT: usize = 32;pub struct Display {buf: UnsafeCell<[u32; WIDTH * HEIGHT]>,}unsafe impl Send for Display {}unsafe impl Sync for Display {}impl Display {fn new() -> Self {Self {buf: UnsafeCell::new([0; WIDTH * HEIGHT]),}}pub fn get_buffer(&self) -> &[u32] {&(unsafe { &*self.buf.get() })[..]}fn get_buffer_mut(&self) -> &mut [u32] {unsafe { &mut *self.buf.get() }}fn clear(&self) {for px in self.get_buffer_mut() {*px = u32::MIN;}}fn get_px(&self, x: u8, y: u8) -> u8 {// println!("getpx {x} {y}");let x = x as usize;let y = y as usize;debug_assert!(x < WIDTH);debug_assert!(y < HEIGHT);let px = self.get_buffer()[y * WIDTH + x];if px == u32::MIN {0} else {1}}fn put_px(&self, x: u8, y: u8, px: u8) {// println!("putpx {x} {y} {px}");debug_assert!(px == 0 || px == 1);let x = x as usize;let y = y as usize;debug_assert!(x < WIDTH);debug_assert!(y < HEIGHT);let px = if px == 0 { u32::MIN } else { u32::MAX };self.get_buffer_mut()[y * WIDTH + x] = px;}}const STACK_LEN: usize = 16;struct Stack {buf: [u16; STACK_LEN],idx: i8,}impl Stack {fn new() -> Self {Self {buf: [0; STACK_LEN],idx: -1,}}fn push(&mut self, elem: u16) -> Option<()> {if self.idx as usize == STACK_LEN - 1 {None} else {self.idx += 1;self.buf[self.idx as usize] = elem;Some(())}}fn pop(&mut self) -> Option<u16> {if self.idx == -1 {None} else {let elem = self.buf[self.idx as usize];self.idx -= 1;Some(elem)}}}#[derive(Debug, Clone, Copy)]enum Opcode {ClearScreen,Jump(u16),SetRegNN(u8, u8),AddRegNN(u8, u8),SetRegI(u16),Draw(u8, u8, u8),Ret,Call(u16),SkipEqNN(u8, u8),SkipNeNN(u8, u8),SkipNeReg(u8, u8),SkipEqReg(u8, u8),SetRegReg(u8, u8),Or(u8, u8),And(u8, u8),Xor(u8, u8),AddRegReg(u8, u8),SubRegXY(u8, u8),SubRegYX(u8, u8),ShiftLeft(u8, u8),ShiftRight(u8, u8),JumpRegNNN(u16),RndNN(u8, u8),SkipNotPressed(u8),SkipPressed(u8),SetRegDelay(u8),SetDelayReg(u8),SetSoundReg(u8),AddIReg(u8),GetKey(u8),SetIFont(u8),Bcd(u8),Store(u8),Load(u8),}impl From<u16> for Opcode {fn from(instruction: u16) -> Self {let op = instruction >> 12;let x = ((instruction >> 8) & 0xF) as u8;let y = ((instruction >> 4) & 0xF) as u8;let n = (instruction & 0xF) as u8;let nn = (instruction & 0xFF) as u8;let nnn = instruction & 0xFFF;match op {0 => match nnn {0x0E0 => Opcode::ClearScreen,0x0EE => Opcode::Ret,_ => todo!(),},1 => Opcode::Jump(nnn),2 => Opcode::Call(nnn),3 => Opcode::SkipEqNN(x, nn),4 => Opcode::SkipNeNN(x, nn),5 => Opcode::SkipEqReg(x, y),6 => Opcode::SetRegNN(x, nn),7 => Opcode::AddRegNN(x, nn),8 => match n {0 => Opcode::SetRegReg(x, y),1 => Opcode::Or(x, y),2 => Opcode::And(x, y),3 => Opcode::Xor(x, y),4 => Opcode::AddRegReg(x, y),5 => Opcode::SubRegXY(x, y),6 => Opcode::ShiftRight(x, y),7 => Opcode::SubRegYX(x, y),0xE => Opcode::ShiftLeft(x, y),_ => panic!(),},9 => Opcode::SkipNeReg(x, y),0xA => Opcode::SetRegI(nnn),0xB => Opcode::JumpRegNNN(nnn),0xC => Opcode::RndNN(x, nn),0xD => Opcode::Draw(x, y, n),0xE => match nn {0x9E => Opcode::SkipPressed(x),0xA1 => Opcode::SkipNotPressed(x),_ => panic!(),},0xF => match nn {0x07 => Opcode::SetRegDelay(x),0x15 => Opcode::SetDelayReg(x),0x18 => Opcode::SetSoundReg(x),0x1E => Opcode::AddIReg(x),0x0A => Opcode::GetKey(x),0x29 => Opcode::SetIFont(x),0x33 => Opcode::Bcd(x),0x55 => Opcode::Store(x),0x65 => Opcode::Load(x),_ => panic!(),},_ => todo!("{:x}", instruction),}}}const REGISTER_COUNT: usize = 16;struct RegisterFile {regs: [u8; REGISTER_COUNT],}impl RegisterFile {fn new() -> Self {Self {regs: [0; REGISTER_COUNT],}}pub fn read(&mut self, reg: u8) -> u8 {self.regs[reg as usize]}fn write(&mut self, reg: u8, nn: u8) {self.regs[reg as usize] = nn;}}const START_PROGRAM: u16 = 0x200;const START_NUMBER_FONT: u16 = 0x50;pub struct Chip8 {mem: Memory,pub display: Arc<Display>,stack: Stack,regs: RegisterFile,pc: u16,i: u16,key_pressed: Option<u8>,delay_timer: Option<u8>,sound_timer: Option<u8>,}impl Chip8 {pub fn new(program: &[u8]) -> Self {let mut mem = Memory::new();let display = Arc::new(Display::new());let stack = Stack::new();mem.load_at(START_NUMBER_FONT, &NUMBER_FONT[..]);mem.load_at(START_PROGRAM, program);let regs = RegisterFile::new();Chip8 {mem,display,stack,regs,pc: START_PROGRAM,i: 0,key_pressed: None,delay_timer: None,sound_timer: None,}}pub fn step(&mut self) {// fetchlet first_byte = self.mem.read(self.pc) as u16;let second_byte = self.mem.read(self.pc + 1) as u16;let instruction = first_byte << 8 | second_byte;self.pc += 2;// decodelet opcode = instruction.into();// dbg!(opcode);// executematch opcode {Opcode::ClearScreen => {self.display.clear();}Opcode::Jump(nnn) => self.pc = nnn,Opcode::SetRegNN(x, nn) => self.regs.write(x, nn),Opcode::AddRegNN(x, nn) => {let val = self.regs.read(x);self.regs.write(x, val.wrapping_add(nn))}Opcode::SetRegI(nnn) => self.i = nnn,Opcode::Draw(x, y, n) => {let x = self.regs.read(x) & (WIDTH as u8 - 1);let mut y = self.regs.read(y) & (HEIGHT as u8 - 1);// println!("draw at {x},{y}");self.regs.write(0xF, 0);let mut set_vf = false;let save_x = x;for i in 0..n {let sprite_row = self.mem.read(self.i + i as u16);let mut x = save_x;for j in (0..8).rev() {let mask = 1 << j;let sprite_px = (sprite_row & mask) >> j;let display_px = self.display.get_px(x, y);if sprite_px == 1 {if display_px == 1 {// println!("clear");self.display.put_px(x, y, 0);set_vf |= sprite_px == display_px;} else {self.display.put_px(x, y, 1);}}x += 1;if x as usize == WIDTH {break;}}y += 1;if y as usize == HEIGHT {break;}}if set_vf {self.regs.write(0xF, 1);}}Opcode::Call(nnn) => {self.stack.push(self.pc).unwrap();self.pc = nnn;}Opcode::Ret => {self.pc = self.stack.pop().unwrap();}Opcode::SkipEqNN(x, nn) => {if self.regs.read(x) == nn {self.pc += 2;}}Opcode::SkipNeNN(x, nn) => {if self.regs.read(x) != nn {self.pc += 2;}}Opcode::SkipEqReg(x, y) => {if self.regs.read(x) == self.regs.read(y) {self.pc += 2;}}Opcode::SkipNeReg(x, y) => {if self.regs.read(x) != self.regs.read(y) {self.pc += 2;}}Opcode::SetRegReg(x, y) => {let vy = self.regs.read(y);self.regs.write(x, vy);}Opcode::Or(x, y) => {let vx = self.regs.read(x);let vy = self.regs.read(y);self.regs.write(x, vx | vy);}Opcode::And(x, y) => {let vx = self.regs.read(x);let vy = self.regs.read(y);self.regs.write(x, vx & vy);}Opcode::Xor(x, y) => {let vx = self.regs.read(x);let vy = self.regs.read(y);self.regs.write(x, vx ^ vy);}Opcode::AddRegReg(x, y) => {let vx = self.regs.read(x);let vy = self.regs.read(y);let res = vx as u16 + vy as u16;self.regs.write(x, res as u8);self.regs.write(0xF, (res > u8::MAX as u16) as u8);}Opcode::SubRegXY(x, y) => {let vx = self.regs.read(x);let vy = self.regs.read(y);let vf = (vx > vy) as u8;// println!("{vx} {vy} {vf}");// self.regs.write(0xF, (vx > vy) as u8);self.regs.write(x, vx.wrapping_sub(vy));self.regs.write(0xF, vf);}Opcode::SubRegYX(x, y) => {let vx = self.regs.read(x);let vy = self.regs.read(y);let vf = (vy > vx) as u8;// println!("{vx} {vy} {vf}");self.regs.write(x, vy.wrapping_sub(vx));self.regs.write(0xF, vf);}Opcode::ShiftLeft(x, y) => {let vx = self.regs.read(x);let _vy = self.regs.read(y);// vx = vy;self.regs.write(x, vx << 1);self.regs.write(0xF, (vx & (1 << 7) != 0) as u8);}Opcode::ShiftRight(x, y) => {let vx = self.regs.read(x);let _vy = self.regs.read(y);// vx = vy;self.regs.write(x, vx >> 1);self.regs.write(0xF, (vx & 1 != 0) as u8);}Opcode::JumpRegNNN(nnn) => {let v0 = self.regs.read(0);self.pc = v0 as u16 + nnn;}Opcode::RndNN(x, nn) => {let rnd: u8 = rand::random();self.regs.write(x, rnd & nn);}Opcode::SkipPressed(x) => {let vx = self.regs.read(x);if let Some(key_pressed) = self.key_pressed {if key_pressed == vx {self.pc += 2;}}}Opcode::SkipNotPressed(x) => {let vx = self.regs.read(x);if let Some(key_pressed) = self.key_pressed {if key_pressed != vx {self.pc += 2;}}}Opcode::SetRegDelay(x) => {let val = self.delay_timer.unwrap_or(0);// println!("delay set v{x} = {val}");self.regs.write(x, val);}Opcode::SetDelayReg(x) => {let vx = self.regs.read(x);// println!("delay = {vx}");self.delay_timer = Some(vx);}Opcode::SetSoundReg(x) => {let vx = self.regs.read(x);self.sound_timer = Some(vx);}Opcode::AddIReg(x) => {let vx = self.regs.read(x);self.i += vx as u16;}Opcode::GetKey(x) => {if let Some(key_pressed) = self.key_pressed {self.regs.write(x, key_pressed);} else {// reexecute the instructionself.pc -= 2;}}Opcode::SetIFont(x) => {let vx = self.regs.read(x);self.i = START_NUMBER_FONT + (vx as u16 & 0xF) * 5;}Opcode::Bcd(x) => {let vx = self.regs.read(x);let huns = vx / 100;let tens = (vx / 10) % 10;let ones = vx % 10;// println!("{vx} = {huns} {tens} {ones}");self.mem.write(self.i, huns);self.mem.write(self.i + 1, tens);self.mem.write(self.i + 2, ones);}Opcode::Store(x) => {for i in 0..=x {let vi = self.regs.read(i);self.mem.write(self.i + i as u16, vi);}}Opcode::Load(x) => {for i in 0..=x {let vi = self.mem.read(self.i + i as u16);self.regs.write(i, vi);}}}}pub fn set_key_pressed(&mut self, key: KeyCode) {self.key_pressed = Some(key.to_u8());}pub fn decr_timers(&mut self) {if let Some(delay) = self.delay_timer.take() {if delay != 0 {// println!("decr delay");self.delay_timer = Some(delay - 1);}}if let Some(sound) = self.sound_timer.take() {if sound != 0 {// println!("decr sound");self.sound_timer = Some(sound - 1);}}}pub fn get_delay_timer(&self) -> Option<u8> {self.delay_timer.clone()}// pub fn set_delay_timer(&mut self, val: u8) {// self.delay_timer = Some(val);// }// pub fn set_sound_timer(&mut self, val: u8) {// self.sound_timer = Some(val);// }}
[package]name = "c8"version = "0.1.0"edition = "2021"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies]minifb = "0.24"rand = "0.8"
# This file is automatically @generated by Cargo.# It is not intended for manual editing.version = 3[[package]]name = "autocfg"version = "1.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"[[package]]name = "bitflags"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"[[package]]name = "bumpalo"version = "3.13.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"[[package]]name = "c8"version = "0.1.0"dependencies = ["minifb","rand",][[package]]name = "cc"version = "1.0.79"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"[[package]]name = "cfg-if"version = "1.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"[[package]]name = "cty"version = "0.2.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"[[package]]name = "dlib"version = "0.5.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"dependencies = ["libloading",][[package]]name = "downcast-rs"version = "1.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"[[package]]name = "errno"version = "0.3.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"dependencies = ["errno-dragonfly","libc","windows-sys",][[package]]name = "errno-dragonfly"version = "0.1.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"dependencies = ["cc","libc",][[package]]name = "fastrand"version = "1.9.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"dependencies = ["instant",][[package]]name = "futures"version = "0.3.28"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"dependencies = ["futures-channel","futures-core","futures-executor","futures-io","futures-sink","futures-task","futures-util",][[package]]name = "futures-channel"version = "0.3.28"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"dependencies = ["futures-core","futures-sink",][[package]]name = "futures-core"version = "0.3.28"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"[[package]]name = "futures-executor"version = "0.3.28"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"dependencies = ["futures-core","futures-task","futures-util",][[package]]name = "futures-io"version = "0.3.28"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"[[package]]name = "futures-macro"version = "0.3.28"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"dependencies = ["proc-macro2","quote","syn",][[package]]name = "futures-sink"version = "0.3.28"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"[[package]]name = "futures-task"version = "0.3.28"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"[[package]]name = "futures-util"version = "0.3.28"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"dependencies = ["futures-channel","futures-core","futures-io","futures-macro","futures-sink","futures-task","memchr","pin-project-lite","pin-utils","slab",][[package]]name = "getrandom"version = "0.2.10"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"dependencies = ["cfg-if","libc","wasi",][[package]]name = "hermit-abi"version = "0.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"[[package]]name = "instant"version = "0.1.12"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"dependencies = ["cfg-if","js-sys","wasm-bindgen","web-sys",][[package]]name = "io-lifetimes"version = "1.0.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"dependencies = ["hermit-abi","libc","windows-sys",][[package]]name = "js-sys"version = "0.3.64"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"dependencies = ["wasm-bindgen",][[package]]name = "lazy_static"version = "1.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"[[package]]name = "libc"version = "0.2.147"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"[[package]]name = "libloading"version = "0.8.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb"dependencies = ["cfg-if","windows-sys",][[package]]name = "linux-raw-sys"version = "0.3.8"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"[[package]]name = "log"version = "0.4.19"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"[[package]]name = "memchr"version = "2.5.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"[[package]]name = "memoffset"version = "0.6.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"dependencies = ["autocfg",][[package]]name = "minifb"version = "0.24.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c66a1fdd7e946fe33fe9725012e25836bba3655769bee9ee347cce7de3f396df"dependencies = ["cc","dlib","futures","instant","js-sys","lazy_static","libc","orbclient","raw-window-handle","serde","serde_derive","tempfile","wasm-bindgen-futures","wayland-client","wayland-cursor","wayland-protocols","winapi","x11-dl",][[package]]name = "minimal-lexical"version = "0.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"[[package]]name = "nix"version = "0.24.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"dependencies = ["bitflags","cfg-if","libc","memoffset",][[package]]name = "nom"version = "7.1.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"dependencies = ["memchr","minimal-lexical",][[package]]name = "once_cell"version = "1.18.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"[[package]]name = "orbclient"version = "0.3.45"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "221d488cd70617f1bd599ed8ceb659df2147d9393717954d82a0f5e8032a6ab1"dependencies = ["libc","redox_syscall","sdl2","sdl2-sys",][[package]]name = "pin-project-lite"version = "0.2.10"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"[[package]]name = "pin-utils"version = "0.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"[[package]]name = "pkg-config"version = "0.3.27"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"[[package]]name = "ppv-lite86"version = "0.2.17"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"[[package]]name = "proc-macro2"version = "1.0.64"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da"dependencies = ["unicode-ident",][[package]]name = "quote"version = "1.0.29"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105"dependencies = ["proc-macro2",][[package]]name = "rand"version = "0.8.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"dependencies = ["libc","rand_chacha","rand_core",][[package]]name = "rand_chacha"version = "0.3.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"dependencies = ["ppv-lite86","rand_core",][[package]]name = "rand_core"version = "0.6.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"dependencies = ["getrandom",][[package]]name = "raw-window-handle"version = "0.4.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b800beb9b6e7d2df1fe337c9e3d04e3af22a124460fb4c30fcc22c9117cefb41"dependencies = ["cty",][[package]]name = "redox_syscall"version = "0.3.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"dependencies = ["bitflags",][[package]]name = "rustix"version = "0.37.23"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"dependencies = ["bitflags","errno","io-lifetimes","libc","linux-raw-sys","windows-sys",][[package]]name = "scoped-tls"version = "1.0.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"[[package]]name = "sdl2"version = "0.35.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f7959277b623f1fb9e04aea73686c3ca52f01b2145f8ea16f4ff30d8b7623b1a"dependencies = ["bitflags","lazy_static","libc","sdl2-sys",][[package]]name = "sdl2-sys"version = "0.35.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e3586be2cf6c0a8099a79a12b4084357aa9b3e0b0d7980e3b67aaf7a9d55f9f0"dependencies = ["cfg-if","libc","version-compare",][[package]]name = "serde"version = "1.0.169"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bd51c3db8f9500d531e6c12dd0fd4ad13d133e9117f5aebac3cdbb8b6d9824b0"dependencies = ["serde_derive",][[package]]name = "serde_derive"version = "1.0.169"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "27738cfea0d944ab72c3ed01f3d5f23ec4322af8a1431e40ce630e4c01ea74fd"dependencies = ["proc-macro2","quote","syn",][[package]]name = "slab"version = "0.4.8"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"dependencies = ["autocfg",][[package]]name = "smallvec"version = "1.11.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"[[package]]name = "syn"version = "2.0.24"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "36ccaf716a23c35ff908f91c971a86a9a71af5998c1d8f10e828d9f55f68ac00"dependencies = ["proc-macro2","quote","unicode-ident",][[package]]name = "tempfile"version = "3.6.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"dependencies = ["autocfg","cfg-if","fastrand","redox_syscall","rustix","windows-sys",][[package]]name = "unicode-ident"version = "1.0.10"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73"[[package]]name = "version-compare"version = "0.1.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"[[package]]name = "wasi"version = "0.11.0+wasi-snapshot-preview1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"[[package]]name = "wasm-bindgen"version = "0.2.87"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"dependencies = ["cfg-if","wasm-bindgen-macro",][[package]]name = "wasm-bindgen-backend"version = "0.2.87"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"dependencies = ["bumpalo","log","once_cell","proc-macro2","quote","syn","wasm-bindgen-shared",][[package]]name = "wasm-bindgen-futures"version = "0.4.37"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"dependencies = ["cfg-if","js-sys","wasm-bindgen","web-sys",][[package]]name = "wasm-bindgen-macro"version = "0.2.87"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"dependencies = ["quote","wasm-bindgen-macro-support",][[package]]name = "wasm-bindgen-macro-support"version = "0.2.87"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"dependencies = ["proc-macro2","quote","syn","wasm-bindgen-backend","wasm-bindgen-shared",][[package]]name = "wasm-bindgen-shared"version = "0.2.87"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"[[package]]name = "wayland-client"version = "0.29.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715"dependencies = ["bitflags","downcast-rs","libc","nix","scoped-tls","wayland-commons","wayland-scanner","wayland-sys",][[package]]name = "wayland-commons"version = "0.29.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902"dependencies = ["nix","once_cell","smallvec","wayland-sys",][[package]]name = "wayland-cursor"version = "0.29.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661"dependencies = ["nix","wayland-client","xcursor",][[package]]name = "wayland-protocols"version = "0.29.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6"dependencies = ["bitflags","wayland-client","wayland-commons","wayland-scanner",][[package]]name = "wayland-scanner"version = "0.29.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53"dependencies = ["proc-macro2","quote","xml-rs",][[package]]name = "wayland-sys"version = "0.29.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4"dependencies = ["dlib","lazy_static","pkg-config",][[package]]name = "web-sys"version = "0.3.64"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"dependencies = ["js-sys","wasm-bindgen",][[package]]name = "winapi"version = "0.3.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"dependencies = ["winapi-i686-pc-windows-gnu","winapi-x86_64-pc-windows-gnu",][[package]]name = "winapi-i686-pc-windows-gnu"version = "0.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"[[package]]name = "winapi-x86_64-pc-windows-gnu"version = "0.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"[[package]]name = "windows-sys"version = "0.48.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"dependencies = ["windows-targets",][[package]]name = "windows-targets"version = "0.48.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"dependencies = ["windows_aarch64_gnullvm","windows_aarch64_msvc","windows_i686_gnu","windows_i686_msvc","windows_x86_64_gnu","windows_x86_64_gnullvm","windows_x86_64_msvc",][[package]]name = "windows_aarch64_gnullvm"version = "0.48.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"[[package]]name = "windows_aarch64_msvc"version = "0.48.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"[[package]]name = "windows_i686_gnu"version = "0.48.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"[[package]]name = "windows_i686_msvc"version = "0.48.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"[[package]]name = "windows_x86_64_gnu"version = "0.48.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"[[package]]name = "windows_x86_64_gnullvm"version = "0.48.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"[[package]]name = "windows_x86_64_msvc"version = "0.48.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"[[package]]name = "x11-dl"version = "2.21.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f"dependencies = ["libc","once_cell","pkg-config",][[package]]name = "xcursor"version = "0.3.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7"dependencies = ["nom",][[package]]name = "xml-rs"version = "0.8.15"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5a56c84a8ccd4258aed21c92f70c0f6dea75356b6892ae27c24139da456f9336"
.git.DS_Store# Added by cargo/target
.git.DS_Store