chore: limpopo update
This commit is contained in:
		
							
								
								
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| **/target | ||||
| **/zig-cache | ||||
| **/.vscode | ||||
| **/bin | ||||
| **/rom | ||||
| **/.gitignore | ||||
							
								
								
									
										1
									
								
								2020-09-26/fizz_buzz/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								2020-09-26/fizz_buzz/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +0,0 @@ | ||||
| /target | ||||
							
								
								
									
										1571
									
								
								2020-11-02/pw313/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1571
									
								
								2020-11-02/pw313/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										14
									
								
								2020-11-02/pw313/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								2020-11-02/pw313/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| [package] | ||||
| name = "pw313" | ||||
| version = "0.1.0" | ||||
| authors = ["Rekai Musuka <rekai@musuka.dev>"] | ||||
| edition = "2018" | ||||
|  | ||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||
|  | ||||
| [dependencies] | ||||
| uvc = "0.1" | ||||
| winit = "0.23" | ||||
| sdl2 = { version = "0.34" } | ||||
| anyhow = "1.0" | ||||
| image = "0.23" | ||||
							
								
								
									
										172
									
								
								2020-11-02/pw313/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								2020-11-02/pw313/src/main.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,172 @@ | ||||
| use anyhow::Result; | ||||
| use sdl2::{ | ||||
|     event::Event, | ||||
|     keyboard::Keycode, | ||||
|     pixels::PixelFormatEnum, | ||||
|     render::{Texture, TextureCreator}, | ||||
|     surface::Surface, | ||||
|     video::WindowContext, | ||||
| }; | ||||
| use std::sync::{ | ||||
|     atomic::{AtomicUsize, Ordering}, | ||||
|     Arc, Mutex, | ||||
| }; | ||||
| use uvc::{Context, Device, DeviceHandle}; | ||||
|  | ||||
| fn log_found_device(device: &Device) -> Result<()> { | ||||
|     let info = device.description()?; | ||||
|  | ||||
|     println!( | ||||
|         "Found device: Bus {:03} Device {:03} : ID {:04x}:{:04x} {} ({})", | ||||
|         device.bus_number(), | ||||
|         device.device_address(), | ||||
|         info.vendor_id, | ||||
|         info.product_id, | ||||
|         info.product.unwrap_or_else(|| "Unknown".to_string()), | ||||
|         info.manufacturer.unwrap_or_else(|| "Unknown".to_string()), | ||||
|     ); | ||||
|  | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| fn log_device_settings(device: &DeviceHandle) { | ||||
|     println!( | ||||
|         "Scanning mode: {:?}\nAuto-exposure mode: {:?}\nAuto-exposure priority: {:?}\nAbsolute exposure: {:?}\nRelative exposure: {:?}\nAboslute focus: {:?}\nRelative focus: {:?}", | ||||
|         device.scanning_mode(), | ||||
|         device.ae_mode(), | ||||
|         device.ae_priority(), | ||||
|         device.exposure_abs(), | ||||
|         device.exposure_rel(), | ||||
|         device.focus_abs(), | ||||
|         device.focus_rel(), | ||||
|     ); | ||||
| } | ||||
|  | ||||
| fn main() { | ||||
|     let uvc_ctx = Context::new().expect("Could not create context"); | ||||
|     let device = uvc_ctx | ||||
|         .find_device(Some(0x07ca), Some(0x313a), None) | ||||
|         .expect("Unable to find the AVerMedia PW313"); | ||||
|  | ||||
|     log_found_device(&device).unwrap(); | ||||
|  | ||||
|     let device = device.open().expect("Unable to open webcam."); | ||||
|     let format = device | ||||
|         .get_preferred_format(|x, y| { | ||||
|             if x.fps >= y.fps && x.width * x.height >= y.width * y.height { | ||||
|                 x | ||||
|             } else { | ||||
|                 y | ||||
|             } | ||||
|         }) | ||||
|         .unwrap(); | ||||
|  | ||||
|     println!("Chosen format: {:?}", format); | ||||
|  | ||||
|     let mut stream = device.get_stream_handle_with_format(format).unwrap(); | ||||
|     log_device_settings(&device); | ||||
|  | ||||
|     let frame_guard = Arc::new(Mutex::new(MyFrame::default())); | ||||
|     let frame_cpy = frame_guard.clone(); | ||||
|  | ||||
|     let counter = Arc::new(AtomicUsize::new(0)); | ||||
|     let stream = stream | ||||
|         .start_stream( | ||||
|             move |frame_ref, count| { | ||||
|                 let mut frame = frame_cpy.lock().unwrap(); | ||||
|  | ||||
|                 *frame = MyFrame { | ||||
|                     data: frame_ref.to_rgb().unwrap().to_bytes().to_owned(), | ||||
|                     width: frame_ref.width(), | ||||
|                     height: frame_ref.height(), | ||||
|                 }; | ||||
|  | ||||
|                 count.fetch_add(1, Ordering::SeqCst); | ||||
|             }, | ||||
|             counter.clone(), | ||||
|         ) | ||||
|         .expect("Could not start stream."); | ||||
|  | ||||
|     let sdl_ctx = sdl2::init().unwrap(); | ||||
|     let video_subsystem = sdl_ctx.video().unwrap(); | ||||
|  | ||||
|     let window = video_subsystem | ||||
|         .window("AVerMedia PW313 Web Camera", format.width, format.height) | ||||
|         .position_centered() | ||||
|         .build() | ||||
|         .unwrap(); | ||||
|  | ||||
|     let mut canvas = window | ||||
|         .into_canvas() | ||||
|         .present_vsync() | ||||
|         .accelerated() | ||||
|         .build() | ||||
|         .unwrap(); | ||||
|     let texture_creator = canvas.texture_creator(); | ||||
|  | ||||
|     'main: loop { | ||||
|         for event in sdl_ctx.event_pump().unwrap().poll_iter() { | ||||
|             match event { | ||||
|                 Event::Quit { .. } | ||||
|                 | Event::KeyDown { | ||||
|                     keycode: Some(Keycode::Escape), | ||||
|                     .. | ||||
|                 } => break 'main, | ||||
|                 _ => {} | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         let texture = do_thing(&frame_guard, &texture_creator); | ||||
|         match texture { | ||||
|             Some(thing) => { | ||||
|                 canvas.copy(&thing, None, None).unwrap(); | ||||
|                 canvas.present(); | ||||
|             } | ||||
|             None => {} | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn do_thing<'a>( | ||||
|     guard: &'a Arc<Mutex<MyFrame>>, | ||||
|     creator: &'a TextureCreator<WindowContext>, | ||||
| ) -> Option<Texture<'a>> { | ||||
|     let mut frame = guard.lock().ok()?; | ||||
|     let width = frame.width; | ||||
|     let height = frame.height; | ||||
|  | ||||
|     if !frame.data.is_empty() { | ||||
|         // Flip Image | ||||
|         let surface = Surface::from_data( | ||||
|             frame.data.as_mut_slice(), | ||||
|             width, | ||||
|             height, | ||||
|             width * (24 / 8), | ||||
|             PixelFormatEnum::RGB24, | ||||
|         ) | ||||
|         .unwrap(); | ||||
|  | ||||
|         Some(Texture::from_surface(&surface, creator).ok()?) | ||||
|     } else { | ||||
|         None | ||||
|     } | ||||
|  | ||||
|     // let surface = Surface::new(600, 800, PixelFormatEnum::RGB24).unwrap(); | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Clone)] | ||||
| struct MyFrame { | ||||
|     data: Vec<u8>, | ||||
|     width: u32, | ||||
|     height: u32, | ||||
| } | ||||
|  | ||||
| impl Default for MyFrame { | ||||
|     fn default() -> Self { | ||||
|         Self { | ||||
|             data: vec![], | ||||
|             width: 600, | ||||
|             height: 800, | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										185
									
								
								2020-11-02/pw313/src/old.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								2020-11-02/pw313/src/old.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,185 @@ | ||||
| use glium::{implement_vertex, uniform}; | ||||
|  | ||||
| use std::error::Error; | ||||
| use std::sync::{Arc, Mutex}; | ||||
|  | ||||
| use glium::Surface; | ||||
| use uvc::{Context, Frame}; | ||||
|  | ||||
| fn frame_to_raw_image( | ||||
|     frame: &Frame, | ||||
| ) -> Result<glium::texture::RawImage2d<'static, u8>, Box<dyn Error>> { | ||||
|     let new_frame = frame.to_rgb()?; | ||||
|     let data = new_frame.to_bytes(); | ||||
|  | ||||
|     let image = glium::texture::RawImage2d::from_raw_rgb( | ||||
|         data.to_vec(), | ||||
|         (new_frame.width(), new_frame.height()), | ||||
|     ); | ||||
|  | ||||
|     Ok(image) | ||||
| } | ||||
|  | ||||
| fn callback_frame_to_image( | ||||
|     frame: &Frame, | ||||
|     data: &mut Arc<Mutex<Option<glium::texture::RawImage2d<u8>>>>, | ||||
| ) { | ||||
|     let image = frame_to_raw_image(frame); | ||||
|     match image { | ||||
|         Err(x) => println!("{:#?}", x), | ||||
|         Ok(x) => { | ||||
|             let mut data = Mutex::lock(&data).unwrap(); | ||||
|             *data = Some(x); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn main() { | ||||
|     let ctx = Context::new().expect("Could not create context"); | ||||
|     let dev = ctx | ||||
|         .find_device(None, None, None) | ||||
|         .expect("Could not find device"); | ||||
|  | ||||
|     let description = dev.description().unwrap(); | ||||
|     println!( | ||||
|         "Found device: Bus {:03} Device {:03} : ID {:04x}:{:04x} {} ({})", | ||||
|         dev.bus_number(), | ||||
|         dev.device_address(), | ||||
|         description.vendor_id, | ||||
|         description.product_id, | ||||
|         description.product.unwrap_or_else(|| "Unknown".to_owned()), | ||||
|         description | ||||
|             .manufacturer | ||||
|             .unwrap_or_else(|| "Unknown".to_owned()) | ||||
|     ); | ||||
|  | ||||
|     // Open multiple devices by enumerating: | ||||
|     // let mut list = ctx.devices().expect("Could not get devices"); | ||||
|     // let dev = list.next().expect("No device available"); | ||||
|  | ||||
|     let devh = dev.open().expect("Could not open device"); | ||||
|  | ||||
|     let format = devh | ||||
|         .get_preferred_format(|x, y| { | ||||
|             if x.fps >= y.fps && x.width * x.height >= y.width * y.height { | ||||
|                 x | ||||
|             } else { | ||||
|                 y | ||||
|             } | ||||
|         }) | ||||
|         .unwrap(); | ||||
|  | ||||
|     println!("Best format found: {:?}", format); | ||||
|     let mut streamh = devh.get_stream_handle_with_format(format).unwrap(); | ||||
|  | ||||
|     println!( | ||||
|             "Scanning mode: {:?}\nAuto-exposure mode: {:?}\nAuto-exposure priority: {:?}\nAbsolute exposure: {:?}\nRelative exposure: {:?}\nAboslute focus: {:?}\nRelative focus: {:?}", | ||||
|             devh.scanning_mode(), | ||||
|             devh.ae_mode(), | ||||
|             devh.ae_priority(), | ||||
|             devh.exposure_abs(), | ||||
|             devh.exposure_rel(), | ||||
|             devh.focus_abs(), | ||||
|             devh.focus_rel(), | ||||
|         ); | ||||
|  | ||||
|     let frame = Arc::new(Mutex::new(None)); | ||||
|     let _stream = streamh | ||||
|         .start_stream(callback_frame_to_image, frame.clone()) | ||||
|         .unwrap(); | ||||
|  | ||||
|     use glium::glutin; | ||||
|     let events_loop = glutin::event_loop::EventLoop::new(); | ||||
|     let window = glutin::window::WindowBuilder::new().with_title("Mirror"); | ||||
|     let context = glutin::ContextBuilder::new(); | ||||
|     let display = glium::Display::new(window, context, &events_loop).unwrap(); | ||||
|  | ||||
|     #[derive(Copy, Clone)] | ||||
|     pub struct QuadVertex { | ||||
|         pos: (f32, f32), | ||||
|     } | ||||
|  | ||||
|     implement_vertex!(QuadVertex, pos); | ||||
|  | ||||
|     let vertices: [QuadVertex; 4] = [ | ||||
|         QuadVertex { pos: (-1.0, -1.0) }, | ||||
|         QuadVertex { pos: (-1.0, 1.0) }, | ||||
|         QuadVertex { pos: (1.0, -1.0) }, | ||||
|         QuadVertex { pos: (1.0, 1.0) }, | ||||
|     ]; | ||||
|  | ||||
|     let indices: [u8; 6] = [0, 1, 2, 1, 3, 2]; | ||||
|  | ||||
|     let vertex_shader_source = r#" | ||||
|     #version 140 | ||||
|     in vec2 pos; | ||||
|     out vec2 v_position; | ||||
|     void main() { | ||||
|         v_position = (pos + 1.0)/2.0; | ||||
|         gl_Position = vec4(-pos.x, -pos.y, 0.0, 1.0); | ||||
|     } | ||||
|     "#; | ||||
|  | ||||
|     let fragment_shader_source = r#" | ||||
|     #version 140 | ||||
|     in vec2 v_position; | ||||
|     out vec4 colour; | ||||
|     uniform sampler2D u_image; | ||||
|     void main() { | ||||
|         vec2 pos = v_position; | ||||
|         colour = texture(u_image, pos); | ||||
|     } | ||||
|     "#; | ||||
|  | ||||
|     let vertices = glium::VertexBuffer::new(&display, &vertices).unwrap(); | ||||
|     let indices = glium::IndexBuffer::new( | ||||
|         &display, | ||||
|         glium::index::PrimitiveType::TrianglesList, | ||||
|         &indices, | ||||
|     ) | ||||
|     .unwrap(); | ||||
|     let program = | ||||
|         glium::Program::from_source(&display, vertex_shader_source, fragment_shader_source, None) | ||||
|             .unwrap(); | ||||
|  | ||||
|     let mut buffer: Option<glium::texture::SrgbTexture2d> = None; | ||||
|     events_loop.run(move |event, _, control_flow| { | ||||
|         if let glutin::event::Event::WindowEvent { event, .. } = event { | ||||
|             if let glutin::event::WindowEvent::CloseRequested = event { | ||||
|                 *control_flow = glutin::event_loop::ControlFlow::Exit; | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         let mut target = display.draw(); | ||||
|         target.clear_color(0.0, 0.0, 1.0, 1.0); | ||||
|  | ||||
|         let mut mutex = Mutex::lock(&frame).unwrap(); | ||||
|  | ||||
|         match mutex.take() { | ||||
|             None => { | ||||
|                 // No new frame to render | ||||
|             } | ||||
|             Some(image) => { | ||||
|                 let image = glium::texture::SrgbTexture2d::new(&display, image) | ||||
|                     .expect("Could not use image"); | ||||
|                 buffer = Some(image); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if let Some(ref b) = buffer { | ||||
|             let uniforms = uniform! { u_image: b }; | ||||
|             target | ||||
|                 .draw( | ||||
|                     &vertices, | ||||
|                     &indices, | ||||
|                     &program, | ||||
|                     &uniforms, | ||||
|                     &Default::default(), | ||||
|                 ) | ||||
|                 .unwrap(); | ||||
|         } | ||||
|  | ||||
|         target.finish().unwrap(); | ||||
|     }); | ||||
| } | ||||
							
								
								
									
										36
									
								
								2021-03-04/password.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								2021-03-04/password.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
|  | ||||
| # Max's Original Solution | ||||
| # password = input("Enter password: ") | ||||
| # contain_digit = False | ||||
| # length = len(password) | ||||
|  | ||||
|  | ||||
| # while contain_digit == False and length < 8: | ||||
| #     for char in password: | ||||
| #         if char.isnumeric(): | ||||
| #             contain_digit = True | ||||
| #             break | ||||
| #         else: | ||||
| #             contain_digit = False | ||||
| #     password = input("Enter valid password: ") | ||||
| #     length = len(password) | ||||
|  | ||||
|  | ||||
| password = input("Enter password: ") | ||||
| valid = False | ||||
|  | ||||
| while not valid: | ||||
|     # Check whether there's a digit | ||||
|     contains_digit = False | ||||
|  | ||||
|     for char in password: | ||||
|         if not contains_digit and char.isnumeric(): | ||||
|             contains_digit = True | ||||
|  | ||||
|     valid = contains_digit and len(password) > 8 | ||||
|  | ||||
|     if not valid: | ||||
|         password = input("Enter valid password: ") | ||||
|  | ||||
|  | ||||
| print("Valid Password") | ||||
							
								
								
									
										17
									
								
								2021-03-04/url_validate.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								2021-03-04/url_validate.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| string = input("Gimme string: ") | ||||
| valid = False | ||||
| start = False | ||||
| end = False | ||||
|  | ||||
| while not valid: | ||||
|     if string[0:6] == "http://": | ||||
|         start = True | ||||
|     else: | ||||
|         start = False | ||||
|     if string[-4:] == ".com": | ||||
|         end = True | ||||
|     else: | ||||
|         end = False | ||||
|     valid = start and end | ||||
|     if not valid: | ||||
|         string = input("gimme good string: ") | ||||
							
								
								
									
										27
									
								
								2021-03-10/zig-hello/build.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								2021-03-10/zig-hello/build.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| const Builder = @import("std").build.Builder; | ||||
|  | ||||
| pub fn build(b: *Builder) void { | ||||
|     // Standard target options allows the person running `zig build` to choose | ||||
|     // what target to build for. Here we do not override the defaults, which | ||||
|     // means any target is allowed, and the default is native. Other options | ||||
|     // for restricting supported target set are available. | ||||
|     const target = b.standardTargetOptions(.{}); | ||||
|  | ||||
|     // Standard release options allow the person running `zig build` to select | ||||
|     // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. | ||||
|     const mode = b.standardReleaseOptions(); | ||||
|  | ||||
|     const exe = b.addExecutable("zig-hello", "src/main.zig"); | ||||
|     exe.setTarget(target); | ||||
|     exe.setBuildMode(mode); | ||||
|     exe.install(); | ||||
|  | ||||
|     const run_cmd = exe.run(); | ||||
|     run_cmd.step.dependOn(b.getInstallStep()); | ||||
|     if (b.args) |args| { | ||||
|         run_cmd.addArgs(args); | ||||
|     } | ||||
|  | ||||
|     const run_step = b.step("run", "Run the app"); | ||||
|     run_step.dependOn(&run_cmd.step); | ||||
| } | ||||
							
								
								
									
										6
									
								
								2021-03-10/zig-hello/src/main.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								2021-03-10/zig-hello/src/main.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| const std = @import("std"); | ||||
|  | ||||
| pub fn main() anyerror!void { | ||||
|     const test_num = 5; | ||||
|     std.log.info("All your codebase are belong to us.", .{}); | ||||
| } | ||||
							
								
								
									
										0
									
								
								2021-03-11/nichol-assignment/img/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								2021-03-11/nichol-assignment/img/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										90
									
								
								2021-03-11/nichol-assignment/index.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								2021-03-11/nichol-assignment/index.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap'); | ||||
|  | ||||
| body { | ||||
|     margin: 0; | ||||
|     font-family: 'Roboto', Arial, Helvetica, sans-serif; | ||||
| } | ||||
|  | ||||
| div.container { | ||||
|     padding: 10px; | ||||
|     display: flex; | ||||
|     background-color: #e5e5e5; | ||||
|     width: 100vw; | ||||
|     height: 100vh; | ||||
|     flex-wrap: wrap; | ||||
| } | ||||
|  | ||||
| div.card-container { | ||||
|     flex: 1 0 calc(100vw / 6); | ||||
|     margin-bottom: 10px; | ||||
|     display: flex; | ||||
|     justify-content: center; | ||||
| } | ||||
|  | ||||
|  | ||||
| div.card { | ||||
|     background-color: white; | ||||
|     height: 500px; | ||||
|     width: 300px; | ||||
|     max-width: 350px; | ||||
|     border-radius: 5px; | ||||
|     box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, 0.1); | ||||
| } | ||||
|  | ||||
| div.card-content { | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     height: calc(500px / 2); | ||||
| } | ||||
|  | ||||
| div.card-content > p { | ||||
|     flex-grow: 1; | ||||
|     margin: 0; | ||||
| } | ||||
|  | ||||
| div.card-content > footer { | ||||
|     height: 2em; | ||||
|     letter-spacing: 3px; | ||||
|     color: #858585 | ||||
| } | ||||
|  | ||||
| div.card-content > footer > hr { | ||||
|     margin: 0; | ||||
|     color: #f5f5f5; | ||||
| } | ||||
|  | ||||
|  | ||||
| div.card > img { | ||||
|     border-radius: inherit; | ||||
|     border-bottom-left-radius: 0; | ||||
|     border-bottom-right-radius: 0; | ||||
|     width: inherit; | ||||
|     height: calc(500px / 2); | ||||
|     object-fit: cover; | ||||
| } | ||||
|  | ||||
| div#card-content { | ||||
|     padding: 5px; | ||||
| } | ||||
|  | ||||
| div#card-content > h2 { | ||||
|     margin: 0; | ||||
|    font-weight: 500; | ||||
| } | ||||
|  | ||||
| div#card-content > p { | ||||
|     font-weight: 400; | ||||
| } | ||||
|  | ||||
| @media (max-width: 1000px) { | ||||
|     div.card-container { | ||||
|         flex: 1 0 calc(100vw / 3); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @media (max-width: 600px) { | ||||
|     div.card-container { | ||||
|         flex: 1 0 100vw; | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										197
									
								
								2021-03-11/nichol-assignment/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								2021-03-11/nichol-assignment/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,197 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
|  | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <link rel="stylesheet" href="index.css"> | ||||
|     <title>Nichol Assignment</title> | ||||
| </head> | ||||
|  | ||||
| <body> | ||||
|     <div class="container"> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="card-container"> | ||||
|             <div class="card"> | ||||
|                 <img src="./img/Zimbabwe-Harare.jpg" alt="A View of Harare from a nearby hill"> | ||||
|                 <div class="card-content"> | ||||
|                     <h2>My Heading</h2> | ||||
|                     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut | ||||
|                         labore | ||||
|                         et dolore magna al</p> | ||||
|                     <footer> | ||||
|                         <hr /> | ||||
|                         <span>TWITTER</span> | ||||
|                     </footer> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </body> | ||||
|  | ||||
| </html> | ||||
							
								
								
									
										29
									
								
								2021-03-16/zig8/build.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								2021-03-16/zig8/build.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| const Builder = @import("std").build.Builder; | ||||
|  | ||||
| pub fn build(b: *Builder) void { | ||||
|     // Standard target options allows the person running `zig build` to choose | ||||
|     // what target to build for. Here we do not override the defaults, which | ||||
|     // means any target is allowed, and the default is native. Other options | ||||
|     // for restricting supported target set are available. | ||||
|     const target = b.standardTargetOptions(.{}); | ||||
|  | ||||
|     // Standard release options allow the person running `zig build` to select | ||||
|     // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. | ||||
|     const mode = b.standardReleaseOptions(); | ||||
|  | ||||
|     const exe = b.addExecutable("zig8", "src/main.zig"); | ||||
|     exe.setTarget(target); | ||||
|     exe.setBuildMode(mode); | ||||
|     exe.linkSystemLibrary("SDL2"); | ||||
|     exe.linkSystemLibrary("c"); | ||||
|     exe.install(); | ||||
|  | ||||
|     const run_cmd = exe.run(); | ||||
|     run_cmd.step.dependOn(b.getInstallStep()); | ||||
|     if (b.args) |args| { | ||||
|         run_cmd.addArgs(args); | ||||
|     } | ||||
|  | ||||
|     const run_step = b.step("run", "Run the app"); | ||||
|     run_step.dependOn(&run_cmd.step); | ||||
| } | ||||
							
								
								
									
										203
									
								
								2021-03-16/zig8/src/cpu.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								2021-03-16/zig8/src/cpu.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| const std = @import("std"); | ||||
| const expect = @import("std").testing.expect; | ||||
| const panic = @import("std").debug.panic; | ||||
| const Dir = @import("std").fs.Dir; | ||||
| const Instruction = @import("instructions.zig").Instruction; | ||||
| const InstrType = @import("instructions.zig").Type; | ||||
| const draw_sprite = @import("display.zig").draw_sprite; | ||||
| const Display = @import("display.zig").Display; | ||||
| const Point = @import("display.zig").Point; | ||||
|  | ||||
| pub const Cpu = struct { | ||||
|     i: u16, | ||||
|     pc: u16, | ||||
|     sp: u16, | ||||
|     v: [16]u8, | ||||
|     stack: [16]u16, | ||||
|     memory: [4096]u8, | ||||
|     disp: Display, | ||||
| }; | ||||
|  | ||||
|  | ||||
| pub fn fetch(cpu: *Cpu) u16 { | ||||
|     const high: u16 = cpu.memory[cpu.pc]; | ||||
|     const low: u16 = cpu.memory[cpu.pc + 1]; | ||||
|      | ||||
|     cpu.pc += 2; | ||||
|  | ||||
|     return high << 8 | low; | ||||
| } | ||||
|  | ||||
| pub fn decode(cpu: *Cpu, word: u16) ?Instruction { | ||||
|     const nib1: u4 = @intCast(u4, (word & 0xF000) >> 12); | ||||
|     const nib2: u4 = @intCast(u4, (word & 0x0F00) >> 8); | ||||
|     const nib3: u4 = @intCast(u4, (word & 0x00F0) >> 4); | ||||
|     const nib4: u4 = @intCast(u4, (word & 0x000F) >> 0); | ||||
|  | ||||
|  | ||||
|     if (nib1 == 0x0) { | ||||
|         // nib2 is 0x0, nib3 is 0xE | ||||
|  | ||||
|         if (nib4 == 0) { | ||||
|             // 0x00E0 | CLS | ||||
|             return Instruction.CLS;  | ||||
|         } | ||||
|  | ||||
|         if (nib4 == 0xE) { | ||||
|             // 0x00EE | RET | ||||
|             return Instruction.RET; | ||||
|         } | ||||
|     } else if (nib1 == 0x1) { | ||||
|         // 0x1nnn | JP addr | ||||
|  | ||||
|         const addr = calc_u12(nib2, nib3, nib4); | ||||
|         return Instruction { .JP = addr }; | ||||
|     } else if (nib1 == 0x2) { | ||||
|         // 0x2nnn | CALL addr | ||||
|  | ||||
|         const addr = calc_u12(nib2, nib3, nib4); | ||||
|         return Instruction { .CALL = addr }; | ||||
|     } else if (nib1 == 0x3) { | ||||
|         // 0x3xkk | SE Vx, u8 | ||||
|  | ||||
|         return Instruction { .SE_3 = .{ .x = nib2, .kk = calc_u8(nib3, nib4) }}; | ||||
|     } else if (nib1 == 0x6) { | ||||
|         // 0x6xkk | LD Vx, u8 | ||||
|  | ||||
|         return Instruction { .LD_6 = .{ .x = nib2, .kk = calc_u8(nib3, nib4) }}; | ||||
|     } else if(nib1 == 0x7) { | ||||
|         // 0x7xkk | LD Vx, kk | ||||
|  | ||||
|         return Instruction { .ADD_7 = .{ .x = nib2, .kk = calc_u8(nib3, nib4) }}; | ||||
|     } else if (nib1 == 0xA) { | ||||
|         // 0xAnnn | LD I, addr | ||||
|         const addr = calc_u12(nib2, nib3, nib4); | ||||
|         return Instruction { .LD_I = addr }; | ||||
|     } else if (nib1 == 0xD) { | ||||
|         // 0xDxyn | DRW Vx, Vy, n | ||||
|         return Instruction {.DRW = .{ .x = nib2, .y = nib3, .n = nib4 }}; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     return null; | ||||
| } | ||||
|  | ||||
| pub fn execute(cpu: *Cpu, instr: Instruction) void { | ||||
|     switch (instr) { | ||||
|         .CLS => std.debug.print("CLS\n", .{}), | ||||
|         .RET => { | ||||
|             std.debug.print("RET\n", .{}); | ||||
|  | ||||
|             cpu.pc = cpu.stack[cpu.sp]; | ||||
|             cpu.sp -= 1; | ||||
|         }, | ||||
|         .JP => |addr| { | ||||
|             std.debug.print("JP 0x{X:}\n", .{ addr }); | ||||
|  | ||||
|             cpu.pc = addr; | ||||
|         }, | ||||
|         .CALL => |addr| { | ||||
|             std.debug.print("CALL 0x{X:}\n", .{ addr }); | ||||
|  | ||||
|             cpu.sp += 1; | ||||
|             cpu.stack[cpu.sp] = cpu.pc; | ||||
|             cpu.pc = addr; | ||||
|         }, | ||||
|         .SE_3 => |args| { | ||||
|             const x = args.x; | ||||
|             const kk = args.kk; | ||||
|             std.debug.print("SE V{}, 0x{X:}\n", .{ x, kk }); | ||||
|  | ||||
|             if (cpu.v[x] != kk) { | ||||
|                 cpu.pc += 2; | ||||
|             } | ||||
|         }, | ||||
|         .LD_6 => |args| { | ||||
|             const x = args.x; | ||||
|             const kk = args.kk; | ||||
|             std.debug.print("LD V{} 0x{X:}\n", .{ x, kk }); | ||||
|  | ||||
|             cpu.v[x] = kk; | ||||
|         }, | ||||
|         .LD_I => |addr| { | ||||
|             std.debug.print("LD I, 0x{X:}\n", .{ addr }); | ||||
|             cpu.i = addr; | ||||
|         }, | ||||
|         .DRW => |args| { | ||||
|             const x = args.x; | ||||
|             const y = args.y; | ||||
|             const n = args.n; | ||||
|             std.debug.print("DRW V{}, V{}, 0x{X:}\n", .{ x, y, n }); | ||||
|  | ||||
|             const draw_pos: Point = .{ .x = cpu.v[x], .y = cpu.v[y] }; | ||||
|             const sprite_data = cpu.memory[cpu.i..(cpu.i + n)]; | ||||
|  | ||||
|             // Draw Sprite | ||||
|             const collision = draw_sprite(&cpu.disp, &draw_pos, &sprite_data); | ||||
|  | ||||
|             cpu.v[0xF] = if (collision) 1 else 0; | ||||
|             // Request Redraw | ||||
|         }, | ||||
|         .ADD_7 => |args| { | ||||
|             const x = args.x; | ||||
|             const kk = args.kk; | ||||
|             std.debug.print("ADD V{}, 0x{X:}\n", .{ x, kk }); | ||||
|  | ||||
|             cpu.v[x] = cpu.v[x] + kk; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn load_rom(cpu: *Cpu, buf: []u8) void { | ||||
|     var mem_index: usize = 0x200; | ||||
|  | ||||
|     for (buf) |byte| { | ||||
|         cpu.memory[mem_index] = byte; | ||||
|         mem_index += 1; | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub fn load_rom_path(cpu: *Cpu, path: []const u8) !void { | ||||
|     var alloc = std.heap.page_allocator; | ||||
|  | ||||
|     const file = try std.fs.cwd().openFile(path, .{ .read = true }); | ||||
|     defer file.close(); | ||||
|  | ||||
|     const file_size = try file.getEndPos(); | ||||
|     const rom_buf = try file.readToEndAlloc(alloc, file_size); | ||||
|  | ||||
|     load_rom(cpu, rom_buf); | ||||
| } | ||||
|  | ||||
| pub fn cycle(cpu: *Cpu) void { | ||||
|     const opcode = fetch(cpu); | ||||
|     const maybe_instr = decode(cpu, opcode); | ||||
|  | ||||
|     if (maybe_instr) |instr| { | ||||
|         execute(cpu, instr); | ||||
|     } else { | ||||
|         panic("Unknown Opcode: 0x{X:}", . { opcode }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn calc_u12(nib2: u4, nib3: u4, nib4: u4) u12 { | ||||
|     return @as(u12, nib2) << 8 | @as(u12, nib3) << 4 | @as(u12, nib4); | ||||
| } | ||||
|  | ||||
| fn calc_u8(nib_a: u4, nib_b: u4) u8 { | ||||
|     return @as(u8, nib_a) << 4 | @as(u8, nib_b); | ||||
| } | ||||
|  | ||||
| test "calc_u12 works" { | ||||
|     const left: u12 = 0xABC; | ||||
|     const right: u12 = calc_u12(0xA, 0xB, 0xC); | ||||
|  | ||||
|     expect(left == right); | ||||
| } | ||||
|  | ||||
| test "calc_u8 works" { | ||||
|     const left: u8 = 0xAB; | ||||
|     const right: u12 = calc_u8(0xA, 0xB); | ||||
|  | ||||
|     expect(left == right); | ||||
| } | ||||
							
								
								
									
										56
									
								
								2021-03-16/zig8/src/display.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								2021-03-16/zig8/src/display.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| const DISPLAY_WIDTH: usize = 64; | ||||
| const DISPLAY_HEIGHT: usize = 32; | ||||
| const std = @import("std"); | ||||
|  | ||||
| pub const Point = struct { | ||||
|     x: u16, | ||||
|     y: u16, | ||||
| }; | ||||
|  | ||||
|  | ||||
| pub const Display =  struct { | ||||
|     buf: [DISPLAY_HEIGHT * DISPLAY_WIDTH]u8, | ||||
|  | ||||
|  | ||||
|     pub fn new() Display { | ||||
|         return .{ | ||||
|             .buf = [_]u8{0x00} ** (DISPLAY_HEIGHT * DISPLAY_WIDTH) | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| pub fn clear(disp: *Display) void { | ||||
|     disp.buf = u8[DISPLAY_WIDTH * DISPLAY_HEIGHT]{0x00}; | ||||
| } | ||||
|  | ||||
| pub fn draw_sprite(disp: *Display, pos: *const Point, data: *const []u8) bool { | ||||
|     var set_vf: bool = false; | ||||
|  | ||||
|     for (data.*) |byte, y_offset| { | ||||
|         var offset_count: u8 = 0; | ||||
|  | ||||
|         while (offset_count < 8) : (offset_count += 1) { | ||||
|             const x_bit_offset = @intCast(u3, offset_count); | ||||
|             const x = @intCast(u8, pos.x + (7 - x_bit_offset)); | ||||
|             const y = @intCast(u8, pos.y + y_offset); | ||||
|  | ||||
|  | ||||
|             const temp = (byte >> x_bit_offset) & 0x01; | ||||
|             const bit = @intCast(u1, temp); | ||||
|             // const bit = @as(u1, temp); | ||||
|  | ||||
|             const i = DISPLAY_WIDTH * y + x; | ||||
|  | ||||
|             if (i >= disp.buf.len) break; | ||||
|  | ||||
|             if (bit == 0x1 and disp.buf[i] == 0x01) { | ||||
|                 set_vf = true; | ||||
|             } | ||||
|  | ||||
|             disp.buf[i] ^= bit; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     return set_vf; | ||||
| } | ||||
							
								
								
									
										12
									
								
								2021-03-16/zig8/src/instructions.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								2021-03-16/zig8/src/instructions.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
|  | ||||
| pub const Instruction = union(enum) { | ||||
|     CLS: void,  // 0x00E0 | ||||
|     RET: void,  // 0x00EE | ||||
|     JP: u12,    // 0x1nnn  | ||||
|     CALL: u12,  // 0x2nnn | ||||
|     SE_3: struct { x: u4, kk: u8 }, // 0x3xkk | ||||
|     LD_6: struct {x: u4, kk: u8}, // 0x6xkk | ||||
|     LD_I: u12,   // 0xAnnn | ||||
|     DRW: struct { x: u4, y: u4, n: u4 }, // 0xDxyn | ||||
|     ADD_7: struct { x: u4, kk: u8 } // 0x7xkk | ||||
| }; | ||||
							
								
								
									
										107
									
								
								2021-03-16/zig8/src/main.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								2021-03-16/zig8/src/main.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| const std = @import("std"); | ||||
| const cpu = @import("cpu.zig"); | ||||
| const Display = @import("display.zig").Display; | ||||
| const c = @cImport({ | ||||
|     @cInclude("SDL2/SDL.h"); | ||||
| }); | ||||
| const assert = @import("std").debug.assert; | ||||
|  | ||||
| // See https://github.com/zig-lang/zig/issues/565 | ||||
| // SDL_video.h:#define SDL_WINDOWPOS_UNDEFINED         SDL_WINDOWPOS_UNDEFINED_DISPLAY(0) | ||||
| // SDL_video.h:#define SDL_WINDOWPOS_UNDEFINED_DISPLAY(X)  (SDL_WINDOWPOS_UNDEFINED_MASK|(X)) | ||||
| // SDL_video.h:#define SDL_WINDOWPOS_UNDEFINED_MASK    0x1FFF0000u | ||||
| const SDL_WINDOWPOS_UNDEFINED = @bitCast(c_int, c.SDL_WINDOWPOS_UNDEFINED_MASK); | ||||
|  | ||||
| extern fn SDL_PollEvent(event: *c.SDL_Event) c_int; | ||||
|  | ||||
| // SDL_RWclose is fundamentally unrepresentable in Zig, because `ctx` is | ||||
| // evaluated twice. One could make the case that this is a bug in SDL, | ||||
| // especially since the docs list a real function prototype that would not | ||||
| // have this double-evaluation of the parameter. | ||||
| // If SDL would instead of a macro use a static inline function, | ||||
| // it would resolve the SDL bug as well as make the function visible to Zig | ||||
| // and to debuggers. | ||||
| // SDL_rwops.h:#define SDL_RWclose(ctx)        (ctx)->close(ctx) | ||||
| inline fn SDL_RWclose(ctx: [*]c.SDL_RWops) c_int { | ||||
|     return ctx[0].close.?(ctx); | ||||
| } | ||||
|  | ||||
| pub fn main() !void { | ||||
|     // Initialize SDL2 | ||||
|     if (c.SDL_Init(c.SDL_INIT_VIDEO) != 0) { | ||||
|         c.SDL_Log("Unable to initialize SDL: %s", c.SDL_GetError()); | ||||
|         return error.SDLInitializationFailed; | ||||
|     } | ||||
|     defer c.SDL_Quit(); | ||||
|  | ||||
|     // Create Screen (Maybe introduce scaling somehow?) | ||||
|     const screen = c.SDL_CreateWindow("Zig8", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 320, c.SDL_WINDOW_OPENGL) orelse | ||||
|         { | ||||
|         c.SDL_Log("Unable to create window: %s", c.SDL_GetError()); | ||||
|         return error.SDLInitializationFailed; | ||||
|     }; | ||||
|     defer c.SDL_DestroyWindow(screen); | ||||
|  | ||||
|     // Create Renderer | ||||
|     const renderer = c.SDL_CreateRenderer(screen, -1, c.SDL_RENDERER_ACCELERATED) orelse { | ||||
|         c.SDL_Log("Unable to create renderer: %s", c.SDL_GetError()); | ||||
|         return error.SDLInitializationFailed; | ||||
|     }; | ||||
|     defer c.SDL_DestroyRenderer(renderer); | ||||
|  | ||||
|     // Create RGBA Texture | ||||
|     const texture = c.SDL_CreateTexture(renderer, c.SDL_PIXELFORMAT_RGBA8888, c.SDL_TEXTUREACCESS_STREAMING, 64, 32) orelse { | ||||
|         c.SDL_Log("Unable to create texture: %s", c.SDL_GetError()); | ||||
|         return error.SDLInitializationFailed; | ||||
|     }; | ||||
|     defer c.SDL_DestroyTexture(texture); | ||||
|  | ||||
|     // Initialize CHIP-8 Emulator | ||||
|     var chip8 = cpu.Cpu { | ||||
|         .i = 0x00, | ||||
|         .pc = 0x0200, | ||||
|         .sp = 0x00, | ||||
|         .v = [_]u8{0x0} ** 16, | ||||
|         .stack = [_]u16{0x0} ** 16, | ||||
|         .memory = [_]u8{0x0} ** 4096, | ||||
|         .disp = Display.new(), | ||||
|     }; | ||||
|  | ||||
|     var path = "./bin/IBM Logo.ch8"; | ||||
|  | ||||
|     // Load Game ROM into CHIP-8 Emulator | ||||
|     try cpu.load_rom_path(&chip8, path); | ||||
|  | ||||
|  | ||||
|     // Create Pixel Buffer (Temporary) | ||||
|     const buf_size = 64 * 32 * @sizeOf(u32); | ||||
|     var pixels: [buf_size]u8 = [_]u8{255} ** buf_size; | ||||
|  | ||||
|     // Render | ||||
|     var quit = false; | ||||
|     while (!quit) { | ||||
|  | ||||
|         var buf_ptr: [*c]?*c_void = &@ptrCast(?*c_void, &pixels[0]); | ||||
|  | ||||
|         _ = c.SDL_LockTexture(texture, null, buf_ptr, 64 * @sizeOf(u32)); | ||||
|         c.SDL_UnlockTexture(texture); | ||||
|          | ||||
|         var event: c.SDL_Event = undefined; | ||||
|         while (SDL_PollEvent(&event) != 0) { | ||||
|             switch (event.@"type") { | ||||
|                 c.SDL_QUIT => { | ||||
|                     quit = true; | ||||
|                 }, | ||||
|                 else => {}, | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         _ = c.SDL_RenderClear(renderer); | ||||
|         _ = c.SDL_RenderCopy(renderer, texture, null, null); | ||||
|         c.SDL_RenderPresent(renderer); | ||||
|  | ||||
|         cpu.cycle(&chip8); | ||||
|  | ||||
|         c.SDL_Delay(17); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user