Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
226 changes: 121 additions & 105 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ categories = ["emulators", "games"]
[dependencies]
rand = "^0.3"
clap = "^2.26.1"
sdl2 = "0.30.0"
sdl2 = "0.31.0"
2 changes: 1 addition & 1 deletion src/disassembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ pub fn disassemble(buffer: &[u8]) {

println!();
}
}
}
31 changes: 22 additions & 9 deletions src/display.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
use sdl2;
use sdl2::rect::Point;
use sdl2::pixels::Color;
use sdl2::video::Window;
use sdl2::rect::Point;
use sdl2::render::Canvas;
use sdl2::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 };
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 {
pub fn new(sdl_context: &sdl2::Sdl) -> Display {
let video_subsystem = sdl_context.video().unwrap();

let window = video_subsystem.window("Alvin", 640, 320)
.position_centered().build().unwrap();
let window = video_subsystem
.window("Alvin", 640, 320)
.position_centered()
.build()
.unwrap();

let mut canvas = window.into_canvas().accelerated().build().unwrap();
canvas.set_scale(10.0, 10.0);
Expand All @@ -26,7 +39,7 @@ impl Display {

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

Expand Down Expand Up @@ -81,4 +94,4 @@ impl Display {

self.canvas.present();
}
}
}
14 changes: 8 additions & 6 deletions src/emulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ use sdl2;

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

use std::collections::VecDeque;
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 opcode::Opcode;
use sound::Sound;

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

fn print_debug(&mut self) {
print!("PC[{:#04x}]\tDELAY[{}]\tSOUND[{}]\tI[{:#03x}]", self.program_counter, self.delay_timer, self.sound_timer, self.address_register);
print!(
"PC[{:#04x}]\tDELAY[{}]\tSOUND[{}]\tI[{:#03x}]",
self.program_counter, self.delay_timer, self.sound_timer, self.address_register
);
for i in 0x0..0x10 {
print!("\tV{:X}[{}]", i, self.get_register(i));
}
Expand Down Expand Up @@ -240,7 +243,6 @@ impl System {

self.set_register(first, result);


self.program_counter += WORD_SIZE;
}
Opcode::SubAssignReg(first, second) => {
Expand Down Expand Up @@ -501,4 +503,4 @@ impl System {
fn set_memory(&mut self, address: Address, value: Constant) {
self.memory[address as usize] = value;
}
}
}
61 changes: 44 additions & 17 deletions src/input.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,76 @@
use sdl2;
use sdl2::EventPump;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::EventPump;

pub struct Input {
event_pump: EventPump
event_pump: EventPump,
}

impl Input {
pub fn new(sdl_context: &sdl2::Sdl) -> Input {
let event_pump = sdl_context.event_pump().unwrap();

Input {
event_pump
}
Input { event_pump }
}

pub fn handle_input(&mut self) -> Option<InputAction> {
for event in self.event_pump.poll_iter() {
match event {
Event::Quit { .. } | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => {
return Some(InputAction::Quit);
}
Event::Quit { .. } | Event::KeyUp { keycode: Some(Keycode::Escape), .. } => {
Event::Quit { .. }
| Event::KeyUp {
keycode: Some(Keycode::Escape),
..
} => {
return Some(InputAction::Quit);
}
Event::KeyDown { keycode: Some(Keycode::Return), .. } => {
Event::KeyDown {
keycode: Some(Keycode::Return),
..
} => {
return Some(InputAction::Reset);
}
Event::KeyUp { keycode: Some(Keycode::Return), .. } => {
Event::KeyUp {
keycode: Some(Keycode::Return),
..
} => {
return Some(InputAction::Reset);
}
Event::KeyDown { keycode: Some(Keycode::Space), .. } => {
Event::KeyDown {
keycode: Some(Keycode::Space),
..
} => {
return Some(InputAction::Pause);
}
Event::KeyDown { keycode: Some(Keycode::LeftBracket), .. } => {
Event::KeyDown {
keycode: Some(Keycode::LeftBracket),
..
} => {
return Some(InputAction::DecreaseTick);
}
Event::KeyDown { keycode: Some(Keycode::RightBracket), .. } => {
Event::KeyDown {
keycode: Some(Keycode::RightBracket),
..
} => {
return Some(InputAction::IncreaseTick);
}
Event::KeyDown { keycode: Some(Keycode::Tab), .. } => {
Event::KeyDown {
keycode: Some(Keycode::Tab),
..
} => {
return Some(InputAction::DebugInfo);
}
Event::KeyUp { keycode: Some(Keycode::Tab), .. } => {
Event::KeyUp {
keycode: Some(Keycode::Tab),
..
} => {
return Some(InputAction::DebugInfo);
}
_ => {}
Expand Down Expand Up @@ -90,7 +117,7 @@ pub enum InputAction {
Pause,
DecreaseTick,
IncreaseTick,
DebugInfo
DebugInfo,
}

pub fn key_map(keycode: Keycode) -> Option<u8> {
Expand All @@ -114,6 +141,6 @@ pub fn key_map(keycode: Keycode) -> Option<u8> {
Keycode::X => Some(0x0),
Keycode::C => Some(0xB),
Keycode::V => Some(0xF),
_ => None
_ => None,
};
}
}
54 changes: 27 additions & 27 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ extern crate clap;
extern crate rand;
extern crate sdl2;

mod input;
mod sound;
mod opcode;
mod memory;
mod disassembler;
mod display;
mod emulator;
mod disassembler;
mod input;
mod memory;
mod opcode;
mod sound;

use clap::{App, Arg};

Expand All @@ -24,24 +24,24 @@ use emulator::System;
fn main() {
let matches = App::new("alvin")
.version(crate_version!())
.arg(Arg::with_name("file")
.short("f")
.long("file")
.value_name("FILE")
.help("What file to load")
.takes_value(true)
.required(true)
)
.subcommand(clap::SubCommand::with_name("disassemble"))
.subcommand(clap::SubCommand::with_name("run")
.arg(Arg::with_name("debug")
.long("debug")
.help("Continuously dump emulator state to the command line")
.takes_value(false)
.required(false)
)
)
.get_matches();
.arg(
Arg::with_name("file")
.short("f")
.long("file")
.value_name("FILE")
.help("What file to load")
.takes_value(true)
.required(true),
).subcommand(clap::SubCommand::with_name("disassemble"))
.subcommand(
clap::SubCommand::with_name("run").arg(
Arg::with_name("debug")
.long("debug")
.help("Continuously dump emulator state to the command line")
.takes_value(false)
.required(false),
),
).get_matches();

let filename = matches.value_of("file").expect("file is required");
let file = File::open(filename).expect("file not found");
Expand All @@ -54,12 +54,12 @@ fn main() {
Some("run") => {
let mut system = System::new(buffer);

let dump_state = matches.subcommand_matches("run").unwrap()
let dump_state = matches
.subcommand_matches("run")
.unwrap()
.is_present("debug");
system.run(dump_state);
}
_ => {
println!("ERROR: command invalid or not provided")
}
_ => println!("ERROR: command invalid or not provided"),
}
}
48 changes: 16 additions & 32 deletions src/memory.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,22 @@
// Sprite data borrowed from https://github.com/massung/CHIP-8/blob/master/chip8/rom.go
const SPRITE_DATA: [u8; 0x1C0] = [
// 4x5 low-res mode font sprites (0-F)
0xF0, 0x90, 0x90, 0x90, 0xF0, 0x20, 0x60, 0x20,
0x20, 0x70, 0xF0, 0x10, 0xF0, 0x80, 0xF0, 0xF0,
0x10, 0xF0, 0x10, 0xF0, 0xA0, 0xA0, 0xF0, 0x20,
0x20, 0xF0, 0x80, 0xF0, 0x10, 0xF0, 0xF0, 0x80,
0xF0, 0x90, 0xF0, 0xF0, 0x10, 0x20, 0x40, 0x40,
0xF0, 0x90, 0xF0, 0x90, 0xF0, 0xF0, 0x90, 0xF0,
0x10, 0xF0, 0xF0, 0x90, 0xF0, 0x90, 0x90, 0xE0,
0x90, 0xE0, 0x90, 0xE0, 0xF0, 0x80, 0x80, 0x80,
0xF0, 0xE0, 0x90, 0x90, 0x90, 0xE0, 0xF0, 0x80,
0xF0, 0x80, 0xF0, 0xF0, 0x80, 0xF0, 0x80, 0x80,
0xF0, 0x90, 0x90, 0x90, 0xF0, 0x20, 0x60, 0x20, 0x20, 0x70, 0xF0, 0x10, 0xF0, 0x80, 0xF0, 0xF0,
0x10, 0xF0, 0x10, 0xF0, 0xA0, 0xA0, 0xF0, 0x20, 0x20, 0xF0, 0x80, 0xF0, 0x10, 0xF0, 0xF0, 0x80,
0xF0, 0x90, 0xF0, 0xF0, 0x10, 0x20, 0x40, 0x40, 0xF0, 0x90, 0xF0, 0x90, 0xF0, 0xF0, 0x90, 0xF0,
0x10, 0xF0, 0xF0, 0x90, 0xF0, 0x90, 0x90, 0xE0, 0x90, 0xE0, 0x90, 0xE0, 0xF0, 0x80, 0x80, 0x80,
0xF0, 0xE0, 0x90, 0x90, 0x90, 0xE0, 0xF0, 0x80, 0xF0, 0x80, 0xF0, 0xF0, 0x80, 0xF0, 0x80, 0x80,
// 8x10 high-res mode font sprites (0-F)
0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7,
0x7E, 0x3C, 0x18, 0x38, 0x58, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x3E, 0x7F, 0xC3, 0x06,
0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x3C, 0x7E,
0xC3, 0x03, 0x0E, 0x0E, 0x03, 0xC3, 0x7E, 0x3C,
0x06, 0x0E, 0x1E, 0x36, 0x66, 0xC6, 0xFF, 0xFF,
0x06, 0x06, 0xFF, 0xFF, 0xC0, 0xC0, 0xFC, 0xFE,
0x03, 0xC3, 0x7E, 0x3C, 0x3E, 0x7C, 0xC0, 0xC0,
0xFC, 0xFE, 0xC3, 0xC3, 0x7E, 0x3C, 0xFF, 0xFF,
0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x60, 0x60,
0x3C, 0x7E, 0xC3, 0xC3, 0x7E, 0x7E, 0xC3, 0xC3,
0x7E, 0x3C, 0x3C, 0x7E, 0xC3, 0xC3, 0x7F, 0x3F,
0x03, 0x03, 0x3E, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C, 0x18, 0x38, 0x58, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x3E, 0x7F, 0xC3, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x3C, 0x7E,
0xC3, 0x03, 0x0E, 0x0E, 0x03, 0xC3, 0x7E, 0x3C, 0x06, 0x0E, 0x1E, 0x36, 0x66, 0xC6, 0xFF, 0xFF,
0x06, 0x06, 0xFF, 0xFF, 0xC0, 0xC0, 0xFC, 0xFE, 0x03, 0xC3, 0x7E, 0x3C, 0x3E, 0x7C, 0xC0, 0xC0,
0xFC, 0xFE, 0xC3, 0xC3, 0x7E, 0x3C, 0xFF, 0xFF, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x60, 0x60,
0x3C, 0x7E, 0xC3, 0xC3, 0x7E, 0x7E, 0xC3, 0xC3, 0x7E, 0x3C, 0x3C, 0x7E, 0xC3, 0xC3, 0x7F, 0x3F,
0x03, 0x03, 0x3E, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// 6-bit ASCII character patterns
0x00, // | |
0x10, // | * |
Expand All @@ -49,7 +34,6 @@ const SPRITE_DATA: [u8; 0x1C0] = [
0xD0, // |** * |
0xE0, // |*** |
0xF0, // |**** |

// 6-bit ASCII characters from 0x100-
0x46, 0x3E, 0x56, // @
0x99, 0x9F, 0x4F, // A
Expand Down Expand Up @@ -135,4 +119,4 @@ pub fn load_program(memory: &mut [u8], program: &[u8]) {
memory[current_address] = *byte;
current_address += 1;
}
}
}
Loading