chore: limpopo update

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-03-29 19:25:46 -05:00
parent 7eda2d71ff
commit e9770053dd
18 changed files with 2728 additions and 1 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
**/target
**/zig-cache
**/.vscode
**/bin
**/rom
**/.gitignore

View File

@ -1 +0,0 @@
/target

1571
2020-11-02/pw313/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View 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"

View 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
View 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
View 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")

View 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: ")

View 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);
}

View 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.", .{});
}

View 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;
}
}

View 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
View 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
View 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);
}

View 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;
}

View 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
};

View 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);
}
}