Skip to content

Commit

Permalink
Replace glium with SDL2
Browse files Browse the repository at this point in the history
  • Loading branch information
sigvef committed Jan 31, 2017
1 parent 3380878 commit d4aa8ac
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 131 deletions.
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ nom = "2.0.1"
num = "0.1.30"
gl = "0.6.1"
libc = "0.2.20"
glium = "0.16.0"

[dependencies.sdl2]
version = "0.28.0"
default-features = false
features = ["gfx"]
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# gba-roa
Game Boy Advance: Rusty Oxidation Action - The ROA Emulator

You need some SDL2. Follow these instructions: https://github.com/AngryLawyer/rust-sdl2
106 changes: 15 additions & 91 deletions src/display.rs
Original file line number Diff line number Diff line change
@@ -1,111 +1,35 @@
use interconnect::InterconnectWrite;
use glium::{self, DisplayBuild, Frame, Surface};
use glium::texture::RawImage2d;
use glium::texture::ClientFormat;
use utils::gba_to_display_format;
use utils::B5G5R5_to_B8G8R8;
use sdl2::gfx::primitives::DrawRenderer;
use sdl2::render::Renderer;

pub struct Display {
pub display: glium::backend::glutin_backend::GlutinFacade,
pub program: glium::Program,
pub buf: [u16; 240 * 160],
}

#[derive(Copy, Clone)]
struct Vertex {
position: [f32; 2],
}

implement_vertex!(Vertex, position);

impl Display {
pub fn new() -> Self {
let display = glium::glutin::WindowBuilder::new()
.with_dimensions(240 * 2, 160 * 2)
.with_title("Game Boy Advance: Rusty Oxidation Action - The ROA Emulator")
.build_glium()
.unwrap();

let width = 160;
let height = 240;

let vertex_shader_src = r#"
#version 140
in vec2 position;
out vec2 vuv;
void main() {
vuv = position;
gl_Position = vec4(position, 0.0, 1.0);
}
"#;

let fragment_shader_src = r#"
#version 140
in vec2 vuv;
out vec4 color;
uniform sampler2D tex;
void main() {
color = texture(tex, vuv / 2.0 + 0.5);
}
"#;

let program =
glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None)
.unwrap();

Display {
display: display,
program: program,
buf: [0b0000_0000_0000_0000u16; 240 * 160],
}
}

fn vsync(&self) {
let shape = vec![Vertex { position: [-1.0, -1.0] },
Vertex { position: [1.0, -1.0] },
Vertex { position: [-1.0, 1.0] },
Vertex { position: [-1.0, 1.0] },
Vertex { position: [1.0, -1.0] },
Vertex { position: [1.0, 1.0] }];

let vertex_buffer = glium::VertexBuffer::new(&self.display, &shape).unwrap();
let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

use std::borrow::Cow;
let image = glium::texture::RawImage2d {
data: Cow::from(&self.buf[..]),
width: 240,
height: 160,
format: ClientFormat::U5U5U5U1,
};

let texture = glium::texture::Texture2d::new(&self.display, image).unwrap();
let sampler = texture.sampled()
.magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest);
let uniforms = uniform! {
tex: sampler,
};

let mut target = self.display.draw();
target.clear_color(0.0, 0.0, 0.0, 1.0);
target.draw(&vertex_buffer,
&indices,
&self.program,
&uniforms,
&Default::default())
.unwrap();
target.finish().unwrap();

pub fn draw(&self, renderer: &mut Renderer) {
renderer.clear();
for x in 0..240 {
for y in 0..160 {
renderer.pixel(
x as i16,
y as i16,
B5G5R5_to_B8G8R8(self.buf[y * 160 + x] as u16));
}
}
renderer.present();
}
}

impl InterconnectWrite for Display {
fn write(&mut self, address: u32, word: u32) {
self.buf[address as usize] = gba_to_display_format(word as u16);
self.vsync();
self.buf[address as usize] = word as u16;
}
}
26 changes: 13 additions & 13 deletions src/gamepad.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use glium::glutin::{ElementState, VirtualKeyCode};
use interconnect::InterconnectRead;
use sdl2::keyboard::Keycode;

#[derive(Default, Debug)]
pub struct Gamepad {
Expand All @@ -16,18 +16,18 @@ pub struct Gamepad {
}

impl Gamepad {
pub fn update(&mut self, key_state: ElementState, virtual_key_code: VirtualKeyCode) {
match virtual_key_code {
VirtualKeyCode::W => self.up = key_state == ElementState::Pressed,
VirtualKeyCode::A => self.left = key_state == ElementState::Pressed,
VirtualKeyCode::S => self.down = key_state == ElementState::Pressed,
VirtualKeyCode::D => self.right = key_state == ElementState::Pressed,
VirtualKeyCode::J => self.a = key_state == ElementState::Pressed,
VirtualKeyCode::K => self.b = key_state == ElementState::Pressed,
VirtualKeyCode::U => self.left_bumper = key_state == ElementState::Pressed,
VirtualKeyCode::I => self.right_bumper = key_state == ElementState::Pressed,
VirtualKeyCode::Return => self.start = key_state == ElementState::Pressed,
VirtualKeyCode::P => self.select = key_state == ElementState::Pressed,
pub fn update(&mut self, pressed: bool, keycode: Keycode) {
match keycode {
Keycode::W => self.up = pressed,
Keycode::A => self.left = pressed,
Keycode::S => self.down = pressed,
Keycode::D => self.right = pressed,
Keycode::J => self.a = pressed,
Keycode::K => self.b = pressed,
Keycode::U => self.left_bumper = pressed,
Keycode::I => self.right_bumper = pressed,
Keycode::Return => self.start = pressed,
Keycode::P => self.select = pressed,
_ => (),
}
}
Expand Down
36 changes: 25 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ extern crate nom;
#[macro_use]
extern crate enum_primitive;

extern crate sdl2;

extern crate num;

#[macro_use]
extern crate glium;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

mod cpu;
mod display;
Expand All @@ -28,8 +30,6 @@ mod errors {
use errors::*;
quick_main!(run);

use glium::glutin::Event;
use glium::{DisplayBuild, Surface};
use interconnect::InterconnectWrite;

fn run() -> Result<()> {
Expand All @@ -48,17 +48,31 @@ fn run() -> Result<()> {
gba.interconnect.write(vram_base + 80 * 240 + 120, 0b0_00000_11111_00000);
gba.interconnect.write(vram_base + 80 * 240 + 125, 0b0_11111_00000_00000);

let sdl_context = sdl2::init().unwrap();
let video_subsys = sdl_context.video().unwrap();
let window = video_subsys.window(
"Game Boy Advance: Rusty Oxidation Action - The ROA Emulator", 240, 160)
.position_centered()
.opengl()
.build()
.unwrap();

let mut renderer = window.renderer().build().unwrap();
let mut events = sdl_context.event_pump().unwrap();

loop {
for ev in gba.interconnect.display.display.poll_events() {
match ev {
Event::KeyboardInput(key_state, _, Some(virtual_key_code)) => {
gba.interconnect.gamepad.update(key_state, virtual_key_code)
for event in events.poll_iter() {
match event {
Event::Quit {..} => break,
Event::KeyUp {keycode: Some(keycode), ..} => {
gba.interconnect.gamepad.update(true, keycode)
}
Event::KeyDown {keycode: Some(keycode), ..} => {
gba.interconnect.gamepad.update(false, keycode)
}
Event::Closed => return Ok(()),
_ => (),
}

println!("Keyboard state: {:?}", gba.interconnect.gamepad);
gba.interconnect.display.draw(&mut renderer);
}
}
}
23 changes: 8 additions & 15 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
pub fn gba_to_display_format(gba_format: u16) -> u16 {
(gba_format & 0b0_00000_00000_11111) << 11 | // Red
(gba_format & 0b0_00000_11111_00000) << 1 | // Green
(gba_format & 0b0_11111_00000_00000) >> 9 // Blue
}

#[cfg(test)]
mod tests {
use super::gba_to_display_format;

#[test]
fn test_display_format_conversion() {
let gba_format = 0b0_10001_11111_00000;
let display_format = 0b00000_11111_10001_0;

assert_eq!(gba_to_display_format(gba_format), display_format);
}
pub fn B5G5R5_to_B8G8R8(B5G5R5: u16) -> u32 {
let upscale: [u32; 32] = [0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107,
115, 123, 132, 140, 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239,
247, 255];
upscale[(B5G5R5 & 0b0_00000_00000_11111) as usize] |
(upscale[((B5G5R5 & 0b0_00000_11111_00000) >> 5) as usize] << 8) |
(upscale[((B5G5R5 & 0b0_11111_00000_00000) >> 10) as usize] << 16) |
0xFF000000u32
}

0 comments on commit d4aa8ac

Please sign in to comment.