summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cargo/config.toml6
-rw-r--r--Cargo.lock117
-rw-r--r--Cargo.toml8
-rw-r--r--rust-toolchain.toml2
-rw-r--r--src/lib.rs627
-rw-r--r--src/main.rs130
6 files changed, 548 insertions, 342 deletions
diff --git a/.cargo/config.toml b/.cargo/config.toml
new file mode 100644
index 0000000..118cd95
--- /dev/null
+++ b/.cargo/config.toml
@@ -0,0 +1,6 @@
+[unstable]
+build-std = ["core"]
+
+[build]
+target = ["x86_64-unknown-linux-none"]
+rustflags = ["-Crelocation-model=static"]
diff --git a/Cargo.lock b/Cargo.lock
index 0e6cf8f..ac7ce08 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,5 +3,122 @@
version = 4
[[package]]
+name = "bitflags"
+version = "2.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+
+[[package]]
name = "chip8"
version = "0.1.0"
+dependencies = [
+ "rustix",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.174"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
+
+[[package]]
+name = "rustix"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
diff --git a/Cargo.toml b/Cargo.toml
index 73f1c6d..3793f4e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,3 +4,11 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+rustix = { version = "1.0.8", default-features = false, features = [ "runtime", "stdio" ] }
+
+[profile.dev]
+panic = "abort"
+
+[profile.release]
+lto = true
+panic = "abort"
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index c5794a6..5d56faf 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,2 +1,2 @@
[toolchain]
-channel = "1.85"
+channel = "nightly"
diff --git a/src/lib.rs b/src/lib.rs
index 17a4c6e..f7ac777 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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(())
+// }