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 rate
window.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 rate
window.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 way
window
.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, // 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
];
#[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) {
// fetch
let 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;
// decode
let opcode = instruction.into();
// dbg!(opcode);
// execute
match 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 instruction
self.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