IBM logo mostly working with slight graphical error

This commit is contained in:
BayThylacine 2025-02-14 14:43:04 +11:00
parent bd8f7ed1a4
commit aaccc26abf
4 changed files with 3142 additions and 2 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
/target
/IBMLogo.ch8
/.idea

2829
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,3 +4,9 @@ version = "0.1.0"
edition = "2021"
[dependencies]
clap = { version = "4.5.28", features = ["derive"] }
clap_derive = "4.5.28"
pixels = "0.15.0"
tao = "0.31.1"
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }

View File

@ -1,3 +1,306 @@
fn main() {
println!("Hello, world!");
use std::path::PathBuf;
use clap::Parser;
use std::fs::File;
use std::io::prelude::*;
use std::num::NonZeroU32;
use std::rc::Rc;
use pixels::{Error, Pixels, SurfaceTexture};
use tao::{
event::{Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
keyboard::KeyCode,
};
use tao::dpi::LogicalSize;
use tracing::{info, error};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use std::sync::Arc;
#[derive(Parser, Debug)]
struct Args {
#[arg(short, long)]
file: PathBuf,
}
#[derive(Copy, Clone)]
struct Chip8 {
display: [u64; 32],
index_register: u16,
registers: [u8; 16],
sound_timer: u8,
delay_timer: u8,
ram: [u8; 4096],
pc: u16,
stack: [u8; 64],
stack_pointer: u8,
}
impl Chip8 {
fn new() -> Self {
Chip8 {
display: [0;32],
index_register: 0,
registers: [0;16],
sound_timer: 0,
delay_timer: 0,
ram: [0; 4096],
pc: 0x200,
stack: [0; 64],
stack_pointer: 0,
}
}
fn insert_font(mut self) -> Self {
font_initialiser(&mut self.ram);
self
}
fn load_file(mut self, file: PathBuf) -> Self {
file_reader(&mut self.ram, file);
self
}
fn draw(self, frame: &mut [u8], dimensions: (u32, u32)) -> Self {
for(i, pixel) in frame.chunks_exact_mut(4).enumerate() {
let x = i % dimensions.0 as usize;
let y = i / dimensions.0 as usize;
let sx = (x * 64) / dimensions.0 as usize;
let sy = (y * 32) / dimensions.1 as usize;
let rgba = if get_bit(self.display[sy], sx as u8) {
[0xff, 0xff, 0xff, 0xff]
} else {
[0x00, 0x00, 0x00, 0xff]
};
pixel.copy_from_slice(&rgba);
}
info!("done");
self
}
fn update(&mut self, instructions: u32) -> Self {
for i in 0..instructions {
let pointer = self.pc as usize;
let opcodes: [u8; 4] = [
((self.ram[pointer] & 240) / 16),
(self.ram[pointer] & 15),
((self.ram[pointer + 1] & 240) /16),
(self.ram[pointer + 1] & 15)
];
self.pc += 2;
//info!("{:?}",opcodes);
match opcodes[0] {
0x00 => {
match opcodes[1] {
0x00 => {
match opcodes[2] {
0x0e => {
match opcodes[3] {
0x00 => {
self.clear_screen();
},
_ => {}
}
},
_ => {}
}
},
_ => {}
}
},
0x01 => {
let position = (opcodes[1] as u16) << 8 | (opcodes[2] as u16) << 4 | opcodes[3] as u16;
self.pc = position;
},
0x02 => {
},
0x03 => {
},
0x04 => {
},
0x05 => {
},
0x06 => {
self.registers[opcodes[1] as usize] = opcodes[2] << 4 | opcodes[3];
},
0x07 => {
let value = (opcodes[2] << 4 | opcodes[3]) as u16;
self.registers[opcodes[1] as usize] = (((self.registers[opcodes[1] as usize] as u16) + value) & 255) as u8;
},
0x08 => {
},
0x09 => {
},
0x0a => {
self.index_register = (opcodes[1] as u16) << 8 | (opcodes[2] as u16) << 4 | (opcodes[3] as u16);
},
0x0b => {
},
0x0c => {
},
0x0d => {
let x = self.registers[opcodes[1] as usize] % 64;
let y = self.registers[opcodes[2] as usize] % 32;
self.registers[0x0f] = 0;
for n in 0..opcodes[3] {
let spritedata = self.ram[self.index_register as usize + n as usize];
for i in 0..7 {
let bit = get_bit_u8(spritedata, i);
self.display[(y + n) as usize] = self.display[(y + n) as usize] ^ ((bit as u64) << (x + i));
}
}
},
0x0e => {
},
0x0f => {
},
_ => {
error!("out of scope opcode");
}
}
}
//info!("{:?}",self.display);
*self
}
fn clear_screen(mut self) -> Self {
self.display = [0;32];
self
}
}
fn main() {
tracing_subscriber::registry()
.with(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| "INFO=debug".into()),
)
.with(tracing_subscriber::fmt::layer())
.init();
let args = Args::parse();
let mut chip8 = Chip8::new().insert_font().load_file(args.file);
println!("ram: {:?}", chip8.ram);
let event_loop = EventLoop::new();
let window = { let window = WindowBuilder::new()
.with_title("Chip8 Emulator")
.with_inner_size(LogicalSize::new(320, 240))
.with_min_inner_size(LogicalSize::new(320, 240))
.build(&event_loop)
.unwrap();
Arc::new(window)
};
let mut pixels = {
let window_size = window.inner_size();
let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, Arc::clone(&window));
Pixels::new(window_size.width, window_size.height, surface_texture).unwrap()
};
let test: u64 = 1;
info!("{}", get_bit(test, 0));
event_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent {event, ..} => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::Resized(size) => {
if let Err(e) = pixels.resize_surface(size.width, size.height) {
error!("pixels.resize_surface");
*control_flow = ControlFlow::Exit;
}
},
_ => {}
},
Event::MainEventsCleared => {
info!(chip8.pc);
chip8.update(40);
info!(chip8.pc);
window.request_redraw();
}
Event::RedrawRequested(_) => {
chip8.draw(pixels.frame_mut(), (window.inner_size().width, window.inner_size().height));
if let Err(err) = pixels.render() {
error!("pixels.render");
*control_flow = ControlFlow::Exit;
}
}
_ => {}
}
});
}
fn file_reader(ram: &mut [u8; 4096], file: PathBuf) {
let mut file = File::open(file).unwrap();
let mut file_contents:Vec<u8> = Vec::new();
file.read_to_end(&mut file_contents).unwrap();
for i in 0..file_contents.len() {
ram[i + 0x200] = file_contents[i];
}
}
fn font_initialiser(ram: &mut [u8; 4096]) {
let 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
];
for i in 0..80 {
ram[i + 0x050] = font[i];
}
}
fn get_bit(num: u64, bit: u8) -> bool {
//info!(bit);
if bit <= 63 {
let mask: u64 = 1 << bit;
let bitvalue = ((num & mask)) != 0;
bitvalue
} else {
false
}
}
fn get_bit_u8(num: u8, bit: u8) -> bool {
if bit <= 8 {
let mask: u8 = 128 >> bit;
let bitvalue = (num & mask) != 0;
bitvalue
} else {
false
}
}