Skip to content

Commit

Permalink
Rust 2018
Browse files Browse the repository at this point in the history
  • Loading branch information
mbStavola committed Jan 6, 2019
1 parent 3c331ec commit 02260ac
Show file tree
Hide file tree
Showing 9 changed files with 344 additions and 198 deletions.
343 changes: 238 additions & 105 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ description = "A simple CHIP-8 emulator."
authors = ["Matt Stavola"]
repository = "https://github.com/mbStavola/alvin"
readme = "README.md"

edition = "2018"
keywords = ["CHIP-8", "emulator"]
categories = ["emulators", "games"]

[dependencies]
rand = "^0.3"
clap = "^2.26.1"
sdl2 = "0.30.0"
sdl2 = "^0.32.1"
2 changes: 1 addition & 1 deletion src/disassembler.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use opcode::Opcode;
use crate::opcode::Opcode;

pub fn disassemble(buffer: &[u8]) {
println!("HEX\tOP\tARG1\tARG2\tARG3");
Expand Down
16 changes: 9 additions & 7 deletions src/display.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use sdl2;
use sdl2::rect::Point;
use sdl2::pixels::Color;
use sdl2::video::Window;
use sdl2::render::Canvas;
use sdl2::{
self,
pixels::Color,
rect::Point,
render::Canvas,
video::Window,
};

const BG_COLOR: Color = Color { r: 53, g: 59, b: 115, a: 0xFF };
const FG_COLOR: Color = Color { r: 255, g: 255, b: 41, a: 0xFF };

pub struct Display {
working_screen: [[bool; 32]; 64],
canvas: Canvas<Window>
canvas: Canvas<Window>,
}

impl Display {
Expand All @@ -26,7 +28,7 @@ impl Display {

Display {
working_screen: [[false; 32]; 64],
canvas
canvas,
}
}

Expand Down
43 changes: 23 additions & 20 deletions src/emulator.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
use rand;
use sdl2;
use std::{
collections::VecDeque,
thread,
time::Duration,
};

use rand;
use rand::distributions::{IndependentSample, Range};
use sdl2;

use std::thread;
use std::time::Instant;
use std::collections::VecDeque;

use sound::Sound;
use opcode::Opcode;
use display::Display;
use input::{Input, InputAction};
use memory::{load_fonts, load_program};
use crate::{
display::Display,
input::{Input, InputAction},
memory::{load_fonts, load_program},
opcode::Opcode,
sound::Sound,
};

pub type Address = u16;
pub type Constant = u8;
Expand Down Expand Up @@ -64,7 +67,7 @@ impl System {
}

pub fn run(&mut self, dump_state: bool) -> Result<(), ()> {
let mut tick_rate = 16;
let mut tick_rate: Duration = Duration::from_millis(16);
let mut running = true;
let mut paused = false;

Expand All @@ -85,14 +88,14 @@ impl System {
}
Some(InputAction::Pause) => paused = !paused,
Some(InputAction::DecreaseTick) => {
if tick_rate >= 8 {
tick_rate -= 4;
if tick_rate.as_millis() >= 8 {
tick_rate -= Duration::from_millis(4);
} else {
tick_rate = 4;
tick_rate = Duration::from_millis(4);
}
}
Some(InputAction::IncreaseTick) => {
tick_rate += 4;
tick_rate += Duration::from_millis(4);
}
Some(InputAction::DebugInfo) => {
if !dump_state {
Expand Down Expand Up @@ -194,7 +197,7 @@ impl System {
Opcode::AddAssign(register, constant) => {
let value = self.get_register(register);

let mut result = if let Some(result) = value.checked_add(constant) {
let result = if let Some(result) = value.checked_add(constant) {
result
} else {
(value as u16 + constant as u16) as u8
Expand Down Expand Up @@ -230,7 +233,7 @@ impl System {
let first_value = self.get_register(first);
let second_value = self.get_register(second);

let mut result = if let Some(result) = first_value.checked_add(second_value) {
let result = if let Some(result) = first_value.checked_add(second_value) {
self.set_flag_register(0x0);
result
} else {
Expand Down Expand Up @@ -454,7 +457,7 @@ impl System {
Ok(())
}

fn tick(&mut self, tick_rate: u32) {
fn tick(&mut self, tick_rate: Duration) {
let mut active_delay = self.delay_timer > 0;
let mut active_sound = self.sound_timer > 0;

Expand All @@ -479,7 +482,7 @@ impl System {
}
}

thread::sleep_ms(tick_rate);
thread::sleep(tick_rate);
}

fn get_register(&self, register: Register) -> Constant {
Expand Down
12 changes: 7 additions & 5 deletions src/input.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use sdl2;
use sdl2::EventPump;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::{
self,
event::Event,
EventPump,
keyboard::Keycode,
};

pub struct Input {
event_pump: EventPump
Expand Down Expand Up @@ -90,7 +92,7 @@ pub enum InputAction {
Pause,
DecreaseTick,
IncreaseTick,
DebugInfo
DebugInfo,
}

pub fn key_map(keycode: Keycode) -> Option<u8> {
Expand Down
28 changes: 15 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
#[macro_use]
extern crate clap;
#![feature(duration_as_u128)]

extern crate rand;
extern crate sdl2;
use std::{
fs::File,
io::{
BufRead,
BufReader,
},
};

use clap::{App, Arg, crate_version};

use crate::{
disassembler::disassemble,
emulator::System,
};

mod input;
mod sound;
Expand All @@ -12,15 +23,6 @@ mod display;
mod emulator;
mod disassembler;

use clap::{App, Arg};

use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;

use disassembler::disassemble;
use emulator::System;

fn main() {
let matches = App::new("alvin")
.version(crate_version!())
Expand Down
80 changes: 41 additions & 39 deletions src/opcode.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fmt;

use emulator::{Address, Constant, Register};
use crate::emulator::{Address, Constant, Register};

pub enum Opcode {
Call(Address),
Expand Down Expand Up @@ -52,44 +52,46 @@ impl Opcode {
second_byte & 0xF
);

match nibbles {
(0x0, _, 0xE, 0x0) => Ok(Opcode::Clear),
(0x0, _, 0xE, 0xE) => Ok(Opcode::Return),
(0x0, _, _, _) => Ok(Opcode::Call(build_address(nibbles))),
(0x1, _, _, _) => Ok(Opcode::Goto(build_address(nibbles))),
(0x2, _, _, _) => Ok(Opcode::CallFunction(build_address(nibbles))),
(0x3, _, _, _) => Ok(Opcode::SkipEq(nibbles.1, build_constant(nibbles))),
(0x4, _, _, _) => Ok(Opcode::SkipNEq(nibbles.1, build_constant(nibbles))),
(0x5, _, _, 0x0) => Ok(Opcode::SkipEqReg(nibbles.1, nibbles.2)),
(0x6, _, _, _) => Ok(Opcode::Set(nibbles.1, build_constant(nibbles))),
(0x7, _, _, _) => Ok(Opcode::AddAssign(nibbles.1, build_constant(nibbles))),
(0x8, _, _, 0x0) => Ok(Opcode::Copy(nibbles.1, nibbles.2)),
(0x8, _, _, 0x1) => Ok(Opcode::Or(nibbles.1, nibbles.2)),
(0x8, _, _, 0x2) => Ok(Opcode::And(nibbles.1, nibbles.2)),
(0x8, _, _, 0x3) => Ok(Opcode::Xor(nibbles.1, nibbles.2)),
(0x8, _, _, 0x4) => Ok(Opcode::AddAssignReg(nibbles.1, nibbles.2)),
(0x8, _, _, 0x5) => Ok(Opcode::SubAssignReg(nibbles.1, nibbles.2)),
(0x8, _, _, 0x6) => Ok(Opcode::ShiftRight(nibbles.1, nibbles.2)),
(0x8, _, _, 0x7) => Ok(Opcode::Subtract(nibbles.1, nibbles.2)),
(0x8, _, _, 0xE) => Ok(Opcode::ShiftLeft(nibbles.1, nibbles.2)),
(0x9, _, _, 0x0) => Ok(Opcode::SkipNEqReg(nibbles.1, nibbles.2)),
(0xA, _, _, _) => Ok(Opcode::SetAddressReg(build_address(nibbles))),
(0xB, _, _, _) => Ok(Opcode::JumpOffset(build_address(nibbles))),
(0xC, _, _, _) => Ok(Opcode::SetRand(nibbles.1, build_constant(nibbles))),
(0xD, _, _, _) => Ok(Opcode::Draw(nibbles.1, nibbles.2, nibbles.3)),
(0xE, _, 0x9, 0xE) => Ok(Opcode::SkipKeyPress(nibbles.1)),
(0xE, _, 0xA, 0x1) => Ok(Opcode::SkipNoKeyPress(nibbles.1)),
(0xF, _, 0x0, 0x7) => Ok(Opcode::StoreDelayTimer(nibbles.1)),
(0xF, _, 0x0, 0xA) => Ok(Opcode::StoreKeypress(nibbles.1)),
(0xF, _, 0x1, 0x5) => Ok(Opcode::SetDelayTimer(nibbles.1)),
(0xF, _, 0x1, 0x8) => Ok(Opcode::SetSoundTimer(nibbles.1)),
(0xF, _, 0x1, 0xE) => Ok(Opcode::IncrementAddressReg(nibbles.1)),
(0xF, _, 0x2, 0x9) => Ok(Opcode::StoreSpriteAddress(nibbles.1)),
(0xF, _, 0x3, 0x3) => Ok(Opcode::BinaryCodedDecimal(nibbles.1)),
(0xF, _, 0x5, 0x5) => Ok(Opcode::Dump(nibbles.1)),
(0xF, _, 0x6, 0x5) => Ok(Opcode::Load(nibbles.1)),
_ => Err(build_data(nibbles))
}
let opcode = match nibbles {
(0x0, _, 0xE, 0x0) => Opcode::Clear,
(0x0, _, 0xE, 0xE) => Opcode::Return,
(0x0, _, _, _) => Opcode::Call(build_address(nibbles)),
(0x1, _, _, _) => Opcode::Goto(build_address(nibbles)),
(0x2, _, _, _) => Opcode::CallFunction(build_address(nibbles)),
(0x3, _, _, _) => Opcode::SkipEq(nibbles.1, build_constant(nibbles)),
(0x4, _, _, _) => Opcode::SkipNEq(nibbles.1, build_constant(nibbles)),
(0x5, _, _, 0x0) => Opcode::SkipEqReg(nibbles.1, nibbles.2),
(0x6, _, _, _) => Opcode::Set(nibbles.1, build_constant(nibbles)),
(0x7, _, _, _) => Opcode::AddAssign(nibbles.1, build_constant(nibbles)),
(0x8, _, _, 0x0) => Opcode::Copy(nibbles.1, nibbles.2),
(0x8, _, _, 0x1) => Opcode::Or(nibbles.1, nibbles.2),
(0x8, _, _, 0x2) => Opcode::And(nibbles.1, nibbles.2),
(0x8, _, _, 0x3) => Opcode::Xor(nibbles.1, nibbles.2),
(0x8, _, _, 0x4) => Opcode::AddAssignReg(nibbles.1, nibbles.2),
(0x8, _, _, 0x5) => Opcode::SubAssignReg(nibbles.1, nibbles.2),
(0x8, _, _, 0x6) => Opcode::ShiftRight(nibbles.1, nibbles.2),
(0x8, _, _, 0x7) => Opcode::Subtract(nibbles.1, nibbles.2),
(0x8, _, _, 0xE) => Opcode::ShiftLeft(nibbles.1, nibbles.2),
(0x9, _, _, 0x0) => Opcode::SkipNEqReg(nibbles.1, nibbles.2),
(0xA, _, _, _) => Opcode::SetAddressReg(build_address(nibbles)),
(0xB, _, _, _) => Opcode::JumpOffset(build_address(nibbles)),
(0xC, _, _, _) => Opcode::SetRand(nibbles.1, build_constant(nibbles)),
(0xD, _, _, _) => Opcode::Draw(nibbles.1, nibbles.2, nibbles.3),
(0xE, _, 0x9, 0xE) => Opcode::SkipKeyPress(nibbles.1),
(0xE, _, 0xA, 0x1) => Opcode::SkipNoKeyPress(nibbles.1),
(0xF, _, 0x0, 0x7) => Opcode::StoreDelayTimer(nibbles.1),
(0xF, _, 0x0, 0xA) => Opcode::StoreKeypress(nibbles.1),
(0xF, _, 0x1, 0x5) => Opcode::SetDelayTimer(nibbles.1),
(0xF, _, 0x1, 0x8) => Opcode::SetSoundTimer(nibbles.1),
(0xF, _, 0x1, 0xE) => Opcode::IncrementAddressReg(nibbles.1),
(0xF, _, 0x2, 0x9) => Opcode::StoreSpriteAddress(nibbles.1),
(0xF, _, 0x3, 0x3) => Opcode::BinaryCodedDecimal(nibbles.1),
(0xF, _, 0x5, 0x5) => Opcode::Dump(nibbles.1),
(0xF, _, 0x6, 0x5) => Opcode::Load(nibbles.1),
_ => return Err(build_data(nibbles))
};

Ok(opcode)
}
}

Expand Down
14 changes: 8 additions & 6 deletions src/sound.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use sdl2;
use sdl2::audio::{AudioDevice, AudioCallback, AudioSpecDesired};
use sdl2::{
self,
audio::{AudioCallback, AudioDevice, AudioSpecDesired},
};

pub struct Sound {
device: AudioDevice<SquareWave>
Expand All @@ -12,14 +14,14 @@ impl Sound {
let spec = AudioSpecDesired {
freq: Some(44100),
channels: Some(1),
samples: None
samples: None,
};

let device = audio.open_playback(None, &spec, |spec| {
SquareWave {
phase_inc: 440.0 / spec.freq as f32,
phase: 0.0,
volume: 0.25
volume: 0.25,
}
}).unwrap();

Expand All @@ -40,7 +42,7 @@ impl Sound {
struct SquareWave {
phase_inc: f32,
phase: f32,
volume: f32
volume: f32,
}

impl AudioCallback for SquareWave {
Expand All @@ -49,7 +51,7 @@ impl AudioCallback for SquareWave {
fn callback(&mut self, out: &mut [f32]) {
for x in out.iter_mut() {
*x = match self.phase {
0.0 ... 0.5 => self.volume,
0.0...0.5 => self.volume,
_ => -self.volume
};
self.phase = (self.phase + self.phase_inc) % 1.0;
Expand Down

0 comments on commit 02260ac

Please sign in to comment.